我很想找到一种方法来自动将可转换类型的容器转换成彼此。
例如,我希望这个存在:template<typename Collection, typename T>
Collection<std::weak_ptr<T> > convert(const Collection<std::shared_ptr<T> > &c){
Collection<std::weak_ptr<T> > l;
for (auto &e : c) l.push_back(e);
return l;
}
我实际上想要从参数类型中删除一层实例化模板,并使用不同的模板类型重新实例化它。
更理想的是,我可以编写一个更常用的转换函数;即不假设存在push_back,并且不专门用于shared_ptr转换为weak_ptr的情况。
有没有人知道这是否可行?
答案 0 :(得分:4)
此功能存在,名为std::copy
。
Collection1 a;
Collection2 b;
std::copy(std::begin(a), std::end(a), std::back_inserter(b));
只要为目标容器定义std::back_inserter
且各个元素都可以转换,这适用于任何集合。
如果您需要支持没有back_inserter
的内容,则需要为std::copy
提供自己的迭代器,并确保它适用于您的容器。
如果你想保持集合“类型”并只是交换模板参数,你可以使用它:
template <template<typename> class OutPtr,
template<typename> class InPtr,
template<typename, typename> class Coll,
typename Elem, typename Alloc>
auto transform_ptr_collection(const Coll<InPtr<Elem>, Alloc>& in) ->
Coll<OutPtr<Elem>, Alloc>
{
return Coll<OutPtr<Elem>, Alloc>(std::begin(in), std::end(in));
}
// call it
suto out = transform_ptr_collection<std::weak_ptr>(vector_of_shared_ptr);
但我不推荐它。首选迭代器接口通过集合接口,它们更通用,更易于使用。
答案 1 :(得分:3)
标准容器具有范围构造函数,允许您从可转换容器构造它们:
std::vector<std::weak_ptr<Foo>> weak_vec(shared_vec.begin(), shared_vec.end());
或者对于标准较少的容器,请使用std::copy
。对于可以像std::weak_ptr
一样廉价构建的东西,我会首先构造一个正确大小的容器,然后使用std::copy
:
std::vector<std::weak_ptr<Foo>> weak_vec(shared_vec.size());
std::copy(std::begin(shared_vec), std::end(shared_vec), std::begin(weak_vec));
对于默认构建不那么便宜的东西,您可以使用std::back_inserter
:
std::copy(std::begin(shared_vec), std::end(shared_vec), std::back_inserter(weak_vec));