将shared_ptr的集合转换为weak_ptr的集合

时间:2014-12-14 06:49:08

标签: c++ templates c++11 c++14

我很想找到一种方法来自动将可转换类型的容器转换成彼此。

例如,我希望这个存在:

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的情况。

有没有人知道这是否可行?

2 个答案:

答案 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));