似乎是一个棘手的问题,因为你无法向vector添加新的成员函数。此表单避免了最少量的副本:
std::vector<T>& operator+=(std::vector<T>& lhs, const std::vector<T>& rhs)
但是自我分配失败了,所以唯一适用于自我分配的是:
template <typename T>
std::vector<T>& operator+=(std::vector<T>& lhs, std::vector<T> rhs)
{
lhs.insert(lhs.end(), rhs.begin(), rhs.end());
return lhs;
}
但这需要额外的副本。这样做的正确方法是什么?
在我的问题中,上述形式“不能正常工作”是模棱两可的。因为它们似乎适用于整数(尽管不适用于std :: strings)。有人指出这是因为它未定义的行为。
答案 0 :(得分:3)
问题:
template <typename T>
std::vector<T>& operator+=(std::vector<T>& lhs, const std::vector<T>& rhs)
{
lhs.insert(lhs.end(), rhs.begin(), rhs.end());
return lhs;
}
不是签名,它将传递给insert
的迭代器在插入完成之前变为无效。
只需使用the correct technique for appending a vector to itself,无需额外的副本。
template <typename T>
void concat_in_place(std::vector<T>& lhs, const std::vector<T>& rhs)
{
auto left_count = lhs.size();
auto right_count = rhs.size();
lhs.resize(left_count + right_count);
std::copy_n(rhs.begin(), right_count, lhs.begin() + left_count);
}
答案 1 :(得分:0)
作为一项政策问题,您不应该使用它们之间的运算符来重载两个不同的std
类型。它可能是未定义的行为:标准是模棱两可的。
如果您想在std
容器上使用运算符语法,我建议使用命名运算符。它也更清楚,因为向量上的运算符可以是容器运算符或元素运算符,这就是它们默认缺失的原因。 v +append= v2;
显然正在追加。 (创建一个静态追加对象,并使用向量重载其lhs和rhs运算符,并在中间步骤中使用表达式模板)
// mini named operator library. Only supports + for now:
template<class Kind>
struct named_operator {};
template<class OP, class LHS> struct plus_ {
LHS lhs;
template<class RHS>
decltype(auto) operator=(RHS&&rhs)&&{
return plus_assign(std::forward<LHS>(lhs), OP{}, std::forward<RHS>(rhs));
}
template<class RHS>
decltype(auto) operator+(RHS&&rhs)&&{
return plus(std::forward<LHS>(lhs), OP{}, std::forward<RHS>(rhs));
}
};
template<class Tag, class LHS>
plus_<Tag,LHS> operator+( LHS&& lhs, named_operator<Tag> ) {
return {std::forward<LHS>(lhs)};
}
// creating a named operator:
static struct append_tag:named_operator<append_tag> {} append;
// helper function, finds size of containers and arrays:
template<class T,std::size_t N>
constexpr std::size_t size( T(&)[N] ) { return N; }
template<class C>
constexpr auto size(C&& c)->decltype(c.size()) { return c.size(); }
// implement the vector +append= range:
template<class T, class A, class RHS>
std::vector<T,A>& plus_assign(std::vector<T,A>&lhs, append_tag, RHS&& rhs) {
auto rhs_size = size(rhs);
lhs.reserve(lhs.size()+rhs_size);
using std::begin; using std::end;
copy_n( begin(rhs), rhs_size, back_inserter(lhs) );
return lhs;
}
// implement container +append+ range:
template<class LHS, class RHS>
LHS plus( LHS lhs, append_tag, RHS&& rhs ) {
using std::begin; using std::end; using std::back_inserter;
copy_n( begin(rhs), size(rhs), back_inserter(lhs) );
return std::move(lhs);
}
请注意,std::vector<int> +append= std::list<int> +append+ std::array<double, 3>
适用于上述代码。