使用 C++11 在一行中连接两个 std::vector
Concatenate two std::vectors in one line using C++11
有没有办法使用C++11在一个代码行中连接两个std::vector,第一个在局部变量中定义,第二个从函数返回:
#include <vector>
#include <iostream>
#include <iterator>
std::vector<int> getNewVector()
{
return {4,5,6};
}
int main(int argc, char** argv)
{
std::vector<int> dest;
std::vector<int> src{1,2,3};
dest = src + getNewVector(); //Error: no operator "+" matches these operands
return 0;
}
编辑:与这个问题不同,不使用C++11,我想知道新的C++11标准是否提供了一些有用的功能来帮助我的任务。 例如,即使它不起作用,我也使用了 + 运算符,而只是为了了解我正在寻找的内容。
您可以使用boost::range
库轻松做到这一点。
范围将成为C++标准库的一部分。有关更多详细信息,请参阅标准库的范围。
奖励点:结果向量只有一个内存分配。
#include <vector>
#include <boost/range/join.hpp>
int main() {
std::vector<int> a{1,2,3};
std::vector<int> b{4,5,6};
auto c = boost::copy_range<std::vector<int>>(boost::join(a, b));
}
或者,将其推广到两个以上的输入序列和类型:
template<class T, class U>
auto join(T const& a, U const& b) -> decltype(boost::join(a, b)) {
return boost::join(a, b);
}
template<class T, class U, class... Args>
auto join(T const& a, U const& b, Args const&... args) -> decltype(boost::join(a, join(b, args...))) {
return boost::join(a, join(b, args...));
}
int main() {
std::vector<int> a{1,2,3};
std::list<int> b{4,5,6};
std::set<int> c{7,8,9};
auto d = boost::copy_range<std::vector<int>>(join(a, b, c));
}
同样,它只在boost::copy_range<std::vector<int>>
中执行一个内存分配,因为输入序列长度是已知的。
我们可以利用 l 值和 r 值被传递给operator+
的事实:
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
std::vector<int> getNewVector()
{
return {4, 5, 6};
}
template <class T>
T operator+(const T& l, T&& r)
{
T c{};
c.reserve(l.size() + r.size());
auto bi = std::back_inserter(c);
std::copy(l.begin(), l.end(), bi);
std::move(r.begin(), r.end(), bi);
return c;
}
int main()
{
std::vector<int> dest;
std::vector<int> src{1, 2, 3};
dest = src + getNewVector(); //uses operator "+"
return 0;
}
重载运算符 + 采用 2 倍向量,解决方案无需库提升
#include <vector>
#include <iostream>
template<typename T>
std::vector<T> operator+(std::vector<T> vec1, const std::vector<T>&& vec2)
{
vec1.insert(vec1.end(), vec2.begin(), vec2.end());
return vec1;
}
std::vector<int> getNewVector()
{
return{ 4,5,6 };
}
template<typename T>
void displayVectors(const std::vector<T>& src, const std::vector<T>& dest, const std::vector<T>&& getNewVector)
{
std::cout << "src { ";
for (const auto& itr : src)
std::cout << itr << " ";
std::cout << "}" << std::endl;
std::cout << "getNewVector() { ";
for (const auto& itr : getNewVector)
std::cout << itr << " ";
std::cout << "}" << std::endl;
std::cout << "dest { ";
for (const auto& itr : dest)
std::cout << itr << " ";
std::cout << "}" << std::endl;
}
int main(int argc, char** argv)
{
std::vector<int> dest;
std::vector<int> src{ 1,2,3 };
displayVectors(src, dest, getNewVector());
dest = src + getNewVector();
std::cout << "After operation" << std::endl;
displayVectors(src, dest, getNewVector());
return 0;
}
或带有移动语义
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
template<typename T>
std::vector<T> operator+(std::vector<T> vec1, const std::vector<T>&& vec2)
{
std::move(vec2.begin(), vec2.end(), std::back_inserter(vec1));
return vec1;
}
std::vector<int> getNewVector()
{
return{ 4,5,6 };
}
template<typename T>
void displayVectors(const std::vector<T>& src, const std::vector<T>& dest)
{
std::cout << "src { ";
for (const auto& itr : src)
std::cout << itr << " ";
std::cout << "}" << std::endl;
std::cout << "dest { ";
for (const auto& itr : dest)
std::cout << itr << " ";
std::cout << "}" << std::endl;
}
int main(int argc, char** argv)
{
std::vector<int> dest;
std::vector<int> src{ 1,2,3 };
displayVectors(src, dest);
dest = src + getNewVector();
std::cout << "After operation" << std::endl;
displayVectors(src, dest);
return 0;
}
namespace named_operator {
template<class D>struct make_operator{make_operator(){}};
template<class T, char, class O> struct half_apply { T&& lhs; };
template<class Lhs, class Op>
half_apply<Lhs, '+', Op> operator+( Lhs&& lhs, make_operator<Op> ) {
return {std::forward<Lhs>(lhs)};
}
template<class Lhs, class Op, class Rhs>
auto operator+( half_apply<Lhs, '+', Op>&& lhs, Rhs&& rhs )
-> decltype( named_invoke( std::forward<Lhs>(lhs.lhs), Op{}, std::forward<Rhs>(rhs) ) )
{
return named_invoke( std::forward<Lhs>(lhs.lhs), Op{}, std::forward<Rhs>(rhs) );
}
}
首先是样板库,然后:
namespace ops {
struct concat_t:named_operator::make_operator<concat_t>{};
static const concat_t concat{};
template<class T, class A, class A2>
std::vector<T,A> named_invoke( std::vector<T,A> lhs, concat_t, std::vector<T,A2> const& rhs){
lhs.insert(lhs.end(), rhs.begin(), rhs.end());
return std::move(lhs);
}
}
using ops::concat;
写入+concat+
运算符。 最终用途如下所示:
int main(){
std::vector<int> a{1,2,3};
std::vector<int> b{7,8,9};
for( auto x: a +concat+ a +concat+ b )
std::cout <<x<<'n';
}
活生生的例子。
重载裸+
在std
中是非法的,在根命名空间中是脆弱/危险的。 由于"在子命名空间中doea不起作用"而脆弱,如果您使其过于贪婪,则很危险。concat_t
标记类型可避免两者。
谁想调用函数。 带有()
s 的前缀表示法很烦人。
上面复制左侧(除非 lhs 是临时的(,然后连接 rhs。 将移动内容添加到 rhs 是命名空间ops
中另一个命名的调用函数。 所以a+a+b
拷贝a
,然后扩展拷贝两次。
表达式模板版本可以避免多次调整大小,以解决常见问题。
根据Maxim Egorushkin的suggesion
a.insert(a.end(), b.begin(), b.end());
会更有效率。
如果要修改"B"的值并插入到"A"中,请使用下面的代码 std::transform。
std::transform( b.begin(), b.end(), std::back_inserter(a), [](int i)->int { return i + delta; } );
完整代码
int main()
{
std::vector<int> a = {1,2,3,4,5};
std::vector<int> b = {11,22,33,44,55};
//to copy
a.insert(a.end(), b.begin(), b.end());
//to transform
std::transform( b.begin(), b.end(), std::back_inserter(a), [](int i)->int { return i + delta; } );
return 0;
}
- 使用std::vector的OpenCL矩阵乘法
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- std::vector的包装器,使数组的结构看起来像结构的数组
- 编译器如何区分std::vector的构造函数
- 使用 pqxx 将 std::vector 存储在 postgresql 中,并从数据库中检索它
- 在std::vector上存储带有模板的类实例
- 在main()之外初始化std::vector会导致性能下降(多线程)
- 为什么std::vector比数组慢
- std::vector::迭代器是否可以合法地作为指针
- 如何将二进制格式的 C++ 对象的 std::vector 保存到磁盘?
- 为什么std::vector和std::valarray初始化构造函数不同
- ";结果类型必须是可从输入范围的值类型""构造的;创建std::vector时
- 在没有未定义行为的情况下实现类似std::vector的容器
- 如何调整 std::vector of Eigen::MatrixXd 的大小
- 使用 std::vector::reverse_iterator 将 int 序列化为字节向量?
- 如何将AERT_Allocate与 std:vector 一起使用
- 推导 std::vector::back() 的返回类型
- 如何将原始字节附加到 std::vector?
- std::vector 没有重载函数的实例与参数列表匹配
- 如果 KEY 是 std::list 或 std::vector 而不是值,那么 std::map 的默认行为是什么?