使用带有std :: unique_ptr元素的boost :: multi_index :: multi_index_container的初始化列表

时间:2014-08-23 00:05:04

标签: c++ c++11 unique-ptr initializer-list boost-multi-index

尝试使用初始值设定项列表将值分配到包含任何类型boost::multi_index::multi_index_container个元素的std::unique_ptr对象时,我收到了编译错误。

这是一个简短的例子(也可在Wandbox上找到):

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>

#include <memory>

int main()
{
    boost::multi_index::multi_index_container<std::unique_ptr<int>> foo;

    // Works:
    foo.insert(std::make_unique<int>(0));
    foo.insert(std::make_unique<int>(1));

    // Doesn't work:
    foo = { std::make_unique<int>(0), std::make_unique<int>(1) };
}

如上所示,使用insert()一次插入一个对象,但我真的不必这样做。

我使用Boost 1.56.0并使用Visual C ++ 12.0(Visual Studio 2013 Update 3)进行编译。但是,使用Clang 3.4或GCC 4.9.0进行编译会导致基本相同的错误。

这里是Clang的输出(为了便于阅读而选择):

In file included from test.cpp:1:
In file included from boost/multi_index_container.hpp:20:
boost/detail/allocator_utilities.hpp:153:11: error: call to implicitly-deleted copy constructor of 'std::__1::unique_ptr<int, std::__1::default_delete<int> >'
  new (p) Type(t);
          ^    ~
boost/multi_index/detail/index_base.hpp:105:33: note: in instantiation of function template specialization 'boost::detail::allocator::construct<std::__1::unique_ptr<int, std::__1::default_delete<int> > >' requested here
      boost::detail::allocator::construct(&x->value(),v);
                                ^

boost/multi_index/detail/index_base.hpp:144:12: note: in instantiation of member function 'boost::multi_index::detail::index_base<std::__1::unique_ptr<int, std::__1::default_delete<int> >, boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::identity<std::__1::unique_ptr<int, std::__1::default_delete<int> > >, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > > >::insert_' requested here
    return insert_(v,x,lvalue_tag());
           ^

boost/multi_index/ordered_index.hpp:728:33: note: in instantiation of member function 'boost::multi_index::detail::index_base<std::__1::unique_ptr<int, std::__1::default_delete<int> >, boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::identity<std::__1::unique_ptr<int, std::__1::default_delete<int> > >, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > > >::insert_' requested here
    final_node_type* res=super::insert_(v,position,x,variant);
                                ^

boost/multi_index_container.hpp:657:27: note: in instantiation of function template specialization 'boost::multi_index::detail::ordered_index<boost::multi_index::identity<std::__1::unique_ptr<int, std::__1::default_delete<int> > >, std::__1::less<std::__1::unique_ptr<int, std::__1::default_delete<int> > >, boost::multi_index::detail::nth_layer<1, std::__1::unique_ptr<int, std::__1::default_delete<int> >, boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::identity<std::__1::unique_ptr<int, std::__1::default_delete<int> > >, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > > >, boost::mpl::vector0<mpl_::na>, boost::multi_index::detail::ordered_unique_tag>::insert_<boost::multi_index::detail::lvalue_tag>' requested here
    node_type* res=super::insert_(v,position,x,variant);
                          ^

boost/multi_index_container.hpp:669:12: note: in instantiation of function template specialization 'boost::multi_index::multi_index_container<std::__1::unique_ptr<int, std::__1::default_delete<int> >, boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::identity<std::__1::unique_ptr<int, std::__1::default_delete<int> > >, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > > >::insert_<boost::multi_index::detail::lvalue_tag>' requested here
    return insert_(v,position,detail::lvalue_tag());
           ^

boost/multi_index_container.hpp:339:30: note: in instantiation of member function 'boost::multi_index::multi_index_container<std::__1::unique_ptr<int, std::__1::default_delete<int> >, boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::identity<std::__1::unique_ptr<int, std::__1::default_delete<int> > >, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > > >::insert_' requested here
      hint=x.make_iterator(x.insert_(*first,hint.get_node()).first);
                             ^

test.cpp:15:6: note: in instantiation of member function 'boost::multi_index::multi_index_container<std::__1::unique_ptr<int, std::__1::default_delete<int> >, boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::identity<std::__1::unique_ptr<int, std::__1::default_delete<int> > >, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > > >::operator=' requested here
        foo = { std::make_unique<int>(0), std::make_unique<int>(1) };
            ^

libcxx-3.4/include/c++/v1/memory:2510:31: note: copy constructor is implicitly deleted because 'unique_ptr<int, std::__1::default_delete<int> >' has a user-declared move constructor
    _LIBCPP_INLINE_VISIBILITY unique_ptr(unique_ptr&& __u) _NOEXCEPT
                          ^
1 error generated.

我担心我不太明白这里发生了什么。为什么要调用复制构造函数?这仅仅是Boost的限制吗?有没有可行的解决方法 - 特别是,可以使用我的目标编译器,Visual C ++ 12.0?

1 个答案:

答案 0 :(得分:3)

initializer_list只允许const访问其元素,这意味着它们无法移动,必须复制。

来自N3337,§18.9.1/ 2 [support.initlist]

  

initializer_list<E>类型的对象提供对const E类型对象数组的访问。

因此foo的作业会尝试制作unique_ptr的副本,当然,这会失败。

foo = { std::make_unique<int>(0), std::make_unique<int>(1) };

This answer有一些解决方法,但我不认为它们在这种情况下会有用。