vector > using initialization list

后端 未结 1 562
名媛妹妹
名媛妹妹 2020-12-10 18:19

I have encountered an error: call to implicitly-deleted copy constructor of \'std::__1::unique_ptr >\' when compile code similar to below using c++

相关标签:
1条回答
  • 2020-12-10 18:24

    Initialization lists are wrappers around const arrays.

    unique_ptrs that are const cannot be moved-from.

    We can hack around this (in a perfectly legal way) like this:

    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.

    Use:

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

    If you want to know why initializer lists reference const data, you'll have to track down and read committee minutes or ask someone who was there. I'd guess it is about the principle of least surprise and/or people with bugaboos about mutable data and view types (such as the renaming of array_view to span).

    If you want more than just vectors:

    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;
    }
    

    which still needs massaging to work right with associative containers as we also want to move the key.

    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;
    }
    
    0 讨论(0)
提交回复
热议问题