在具有不同分配器的向量之间转换

Jac*_*oyd 9 c++ allocator c++11

我编写了一个简单的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
Run Code Online (Sandbox Code Playgroud)

什么是允许从转换的最佳方式my_vectorstd::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()]);
   }
Run Code Online (Sandbox Code Playgroud)

但这看起来非常不优雅.在C++ 11中有更好的解决方案吗?

当然,在这种情况下,移动语义是正确的,但我希望复制构造和分配工作而不会产生额外的噪音/打字.

Ker*_* SB 13

你不可能希望绕过明显的副本:std::vector<int> y(x.begin(), x.end();.in中的元素y将被分配std::allocator,而元素x将被你自己的分配器分配,并将被销毁.两个分配器可能有完全不相关的内存指针概念!没有理由一个分配器使用的内存存储与另一个分配器的内存存储有任何关联.

除了制作语义元素副本之外你还能做些什么呢?

如果您不再需要旧容器,您应该采取行动:

std::vector<int> y(std::make_move_iterator(x.begin()),
                   std::make_move_iterator(x.end()));
Run Code Online (Sandbox Code Playgroud)

(这将有助于元素有自己的分配器同意.int当然不是.)

更新:为了加强这一点,请注意的内部数据缓冲区vector<T, Alloc>不是类型T*,而是类型Alloc::pointer.对于两个不同的分配器,没有理由将它们作为相关类型.

  • @JackLloyd:这就是temporaries的生命延伸:`const auto&x = func(); std :: vector <int> y(x.begin(),x.end());`标准容器没有来自容器的构造函数或仅来自迭代器*对*的构造函数.我最好写一个通用的*range*class加上包装来封装迭代器对,让`v.all()`返回`range(v.begin(),v.end())`.但是,我不认为您的原始转换函数会增加任何方便性.它过于严格,并且没有做任何标准容器接口尚未提供的功能. (2认同)

Nik*_*sov 2

嗯,我认为你唯一的选择是完整的副本,例如:

std::vector<int> y( x.begin(), x.end());
Run Code Online (Sandbox Code Playgroud)