Ответ 1
Нет, это невозможно, если вы требуете, чтобы
- не определена вспомогательная функция, а
- результирующий вектор можно объявить
const
.
Есть ли способ построить 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());
Нет, это невозможно, если вы требуете, чтобы
const
.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;
Думаю, вам нужно написать справочную функцию. Я бы написал это как:
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;
}
(Лично я буду беспокоиться только о том, были ли доказательства того, что это было узким местом).
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;
}
Позвольте мне изложить это, сказав, что это взломать, и не даст ответа на вопрос, как это сделать, используя 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());