Построение вектора из конкатенации 2 векторов

Есть ли способ построить vector как конкатенацию 2 vector (кроме создания вспомогательной функции?)

Например:

const vector<int> first = {13};
const vector<int> second = {42};
const vector<int> concatenation = first + second;

Я знаю, что vector не имеет оператора добавления, такого как string, но того поведения, которое я хочу. Такой, что concatenation будет содержать: 13 и 42.

Я знаю, что я могу инициализировать concatenation следующим образом, но это мешает мне сделать concatenation const:

vector<int> concatenation = first;
first.insert(concatenation.end(), second.cbegin(), second.cend()); 

Ответ 1

Нет, это невозможно, если вы требуете, чтобы

  • не определена вспомогательная функция, а
  • результирующий вектор можно объявить const.

Ответ 2

template<typename T>
std::vector<T> operator+(const std::vector<T>& v1, const std::vector<T>& v2){
    std::vector<T> vr(std::begin(v1), std::end(v1));
    vr.insert(std::end(vr), std::begin(v2), std::end(v2));
    return vr;
}

Для этого требуется вспомогательная "функция", но по крайней мере она позволяет использовать ее как

const vector<int> concatenation = first + second;

Ответ 3

Думаю, вам нужно написать справочную функцию. Я бы написал это как:

std::vector<int> concatenate(const std::vector<int>& lhs, const std::vector<int>& rhs)
{
    auto result = lhs;
    std::copy( rhs.begin(), rhs.end(), std::back_inserter(result) );
    return result;
}

Вызов:

    const auto concatenation = concatenate(first, second);

Если векторы, вероятно, будут очень большими (или содержат элементы, которые дорого копируются), вам может потребоваться сначала выполнить reserve, чтобы сохранить перераспределения:

std::vector<int> concatenate(const std::vector<int>& lhs, const std::vector<int>& rhs)
{
    std::vector<int> result;
    result.reserve( lhs.size() + rhs.size() );
    std::copy( lhs.begin(), lhs.end(), std::back_inserter(result) );
    std::copy( rhs.begin(), rhs.end(), std::back_inserter(result) );
    return result;
}

(Лично я буду беспокоиться только о том, были ли доказательства того, что это было узким местом).

Ответ 4

class Vector : public vector<int>
{
public:
    Vector operator+(const Vector& vec);
};

Vector Vector::operator+(const Vector& vec)
{
    for (int i = 0; i < vec.size(); i++)
    {
        this->push_back(vec[i]);
    }

    return *this;
}

Ответ 5

Позвольте мне изложить это, сказав, что это взломать, и не даст ответа на вопрос, как это сделать, используя vector. Вместо этого мы будем зависеть от sizeof(int) == sizeof(char32_t) и использовать u32string для хранения наших данных.

Этот ответ делает чрезвычайно очевидным, что в basic_string можно использовать только примитивы и что для любого примитива размером более 32 бит потребуется написать пользовательский char_traits, но для int мы можем просто использовать u32string.

Квалификацию для этого можно проверить, выполнив:

static_assert(sizeof(int) == sizeof(char32_t));

Как только будет установлено равенство размера, и, зная, что такие вещи, как non const data, и emplace или emplace_back не могут быть использованы, u32string можно использовать как a vector<int> с заметным включением дополнительного оператора:

const vector<int> first = {13};
const vector<int> second = {42};
const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());

[Live Example]