代码之家  ›  专栏  ›  技术社区  ›  Chen

使用初始化列表的向量

  •  5
  • Chen  · 技术社区  · 7 年前

    调用“std::unique\u ptr>”的隐式删除副本构造函数 c++-std=c++14唯一ptr\U向量。cpp-o主

    以下是简化版本:

    头文件“my_头”。h’:

    #include <iostream>
    #include <string>
    #include <memory>
    #include <vector>
    
    class A{
    public:
        A() : n(0) {}
        A(int val) : n(val) {} 
        A(const A &rhs): n(rhs.n) {}
        A(A &&rhs) : n(std::move(rhs.n)) {}
        A& operator=(const A &rhs) { n = rhs.n; return *this; }
        A& operator=(A &&rhs) { n = std::move(rhs.n); return *this; }
        ~A() {}
    
        void print() const { std::cout << "class A: " << n << std::endl; }
    private:
        int n;
    };
    
    namespace {
        std::vector<std::unique_ptr<A>> vecA = {
            std::make_unique<A>(1),
            std::make_unique<A>(2),
            std::make_unique<A>(3),
            std::make_unique<A>(4)
        };
    }
    

    unique_ptr_vector.cpp :

    #include "my_header.h"
    
    using namespace std;
    
    int main()
    {
        for(const auto &ptrA : vecA){
            ptrA->print();
        }
        return 0;
    }
    

    我真的需要使用 push_back(std::make_unique<A>(<some_number>)) 对于每个组件, 或者,在标题中填充容器的首选方法是什么?或者这总体上是个坏主意?

    我见过这样的问题 this one , this one

    我现在知道初始化列表似乎不可能。但是人们通常用什么做 container<unique_ptr> . 我应该简单地避免在标题中初始化它吗。。。

    1 回复  |  直到 4 年前
        1
  •  16
  •   Asaaj Yakk - Adam Nevraumont    5 年前

    初始化列表是包装器 const 阵列。

    unique_ptr 是的 常数 无法从中移动。

    我们可以这样绕过它(以完全合法的方式):

    template<class T>
    struct movable_il {
      mutable T t;
      operator T() const&& { return std::move(t); }
      movable_il( T&& in ): t(std::move(in)) {}
    };
    
    template<class T, class A=std::allocator<T>>
    std::vector<T,A> vector_from_il( std::initializer_list< movable_il<T> > il ) {
      std::vector<T,A> r( std::make_move_iterator(il.begin()), std::make_move_iterator(il.end()) );
      return r;
    }
    

    Live example .

    使用:

    auto v = vector_from_il< std::unique_ptr<int> >({
      std::make_unique<int>(7), 
      std::make_unique<int>(3)
    });
    

    如果你想知道 为什么? 初始值设定项列出了参考常数数据,你们必须追踪并阅读委员会会议记录,或者询问在场的人。我想这是关于最小惊讶原则和/或对可变数据和视图类型(例如重命名 array_view span

    如果您想要的不仅仅是向量:

    template<class C, class T=typename C::value_type>
    C container_from_il( std::initializer_list< movable_il<T> > il ) {
      C r( std::make_move_iterator(il.begin()), std::make_move_iterator(il.end()) );
      return r;
    }
    

    这仍然需要按摩才能正确使用关联容器,因为我们还想移动关键点。

    template<class VT>
    struct fix_vt {
      using type=VT;
    };
    template<class VT>
    using fix_vt_t = typename fix_vt<VT>::type;
    template<class VT>
    struct fix_vt<const VT>:fix_vt<VT>{};
    template<class K, class V>
    struct fix_vt<std::pair<K,V>>{
      using type=std::pair<
        typename std::remove_cv<K>::type,
        typename std::remove_cv<V>::type
      >;
    };
    
    template<class C, class T=fix_vt_t<typename C::value_type>>
    C container_from_il( std::initializer_list< movable_il<T> > il ) {
      C r( std::make_move_iterator(il.begin()), std::make_move_iterator(il.end()) );
      return r;
    }