我编写了一个简单的C ++ 11样式的有状态分配器类型。给定
template<typename T> class my_allocator {
// the usual stuff
};
template<typename T> using my_vector = std::vector<T, my_allocator<T>>;
my_vector<int> x;
std::vector<int> y = x; // error
使用默认分配器允许从my_vector
转换为std::vector
的最佳方式是什么? GCC 4.7(最近的svn)说
error: conversion from 'my_vector<int> {aka std::vector<int, my_allocator<int>>}' to non-scalar type 'std::vector<int>' requested
显然,这可以通过简单的转换功能完成,例如
template<typename T> std::vector<T> to_std_vec(const my_vector<T>& v) {
return std::vector<T>(&v[0], &v[v.size()]);
}
但这似乎很不优雅。在C ++ 11中有更好的解决方案吗?
当然,在这种情况下移动语义是正确的,但是我希望复制构造和赋值工作而不会产生额外的噪音/打字。
答案 0 :(得分:13)
你不可能希望绕过明显的副本:std::vector<int> y(x.begin(), x.end();
。 y
中的元素将由std::allocator
分配,而x
中的元素由您自己的分配器分配,并将被销毁。这两个分配器可以完全不相关的内存和指针的概念!没有理由一个分配器使用的内存存储与另一个分配器的内存存储有任何关联。
除了制作语义元素副本之外,你能做些什么?
如果您不再需要旧容器,则应该执行移动:
std::vector<int> y(std::make_move_iterator(x.begin()),
std::make_move_iterator(x.end()));
(如果元素有自己的分配器同意,这将有所帮助。当然不适用于int
。)
更新:为了强调这一点,请注意vector<T, Alloc>
的内部数据缓冲区不是类型T*
,而是类型为Alloc::pointer
。没有理由说这些是两个不同分配器的相关类型。
答案 1 :(得分:2)
嗯,我认为你唯一的选择就是:
std::vector<int> y( x.begin(), x.end());
答案 2 :(得分:2)
您的问题有三种解决方案:
我。如果您的矢量'y'尚不存在,您可以使用:
std::vector<int> y(x.begin(), x.end());
II。如果您的矢量'y'已经存在,您可以使用:(例如,对于某个类的成员)
this->y.assign(x.begin(), x.end());
这两种填充向量的方法不是查看容器类型。 (因此也就是分配器类型)
III。另一种解决方案是创建一个父类,它可以用作std分配器和你自己的分配器之间的分配器适配器。在这种情况下,您的2个分配器具有相同的类型,并且可以与operator =()等矢量方法一起使用。