[Boost-bugs] [Boost C++ Libraries] #13405: Tree-based containers have troubles with move-only types.

Subject: [Boost-bugs] [Boost C++ Libraries] #13405: Tree-based containers have troubles with move-only types.
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2018-01-17 17:34:53


#13405: Tree-based containers have troubles with move-only types.
--------------------------------------------+---------------------------
 Reporter: Mikhail Kremniov <mkremniov@…> | Owner: Ion Gaztañaga
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: container
  Version: Boost 1.66.0 | Severity: Problem
 Keywords: |
--------------------------------------------+---------------------------
 Specifically, move assignment doesn't work.

 E.g. test.cpp:
 {{{
 #include <boost/container/set.hpp>
 #include <memory>

 int main()
 {
     boost::container::set<std::unique_ptr<int>> set1, set2;
     set2 = std::move(set1);
 }
 }}}

 Compiling with clang 5:
 {{{
 $ clang++-5.0 ~/tmp/test.cpp -std=c++14 -o test -stdlib=libc++ -isystem
 ./boost_1_66_0
 In file included from /home/brd/tmp/test.cpp:1:
 In file included from ./boost_1_66_0/boost/container/set.hpp:28:
 In file included from ./boost_1_66_0/boost/container/detail/tree.hpp:25:
 ./boost_1_66_0/boost/container/allocator_traits.hpp:415:51: error: call to
 implicitly-deleted copy constructor of 'std::__1::unique_ptr<int,
 std::__1::default_delete<int> >'
       { ::new((void*)p, boost_container_new_t())
 T(::boost::forward<Args>(args)...); }
                                                   ^
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ./boost_1_66_0/boost/container/allocator_traits.hpp:360:28: note: in
 instantiation of function template specialization
 'boost::container::allocator_traits<boost::container::new_allocator<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
 boost::container::tree_type_enum::red_black_tree,
       true> > >::priv_construct<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, const std::__1::unique_ptr<int,
 std::__1::default_delete<int> > &>' requested here
          allocator_traits::priv_construct(flag, a, p,
 ::boost::forward<Args>(args)...);
                            ^
 ./boost_1_66_0/boost/container/detail/node_alloc_holder.hpp:168:36: note:
 in instantiation of function template specialization
 'boost::container::allocator_traits<boost::container::new_allocator<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
 boost::container::tree_type_enum::red_black_tree,
       true> > >::construct<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, const std::__1::unique_ptr<int,
 std::__1::default_delete<int> > &>' requested here
       allocator_traits<NodeAlloc>::construct
                                    ^
 ./boost_1_66_0/boost/container/detail/tree.hpp:389:26: note: in
 instantiation of function template specialization
 'boost::container::container_detail::node_alloc_holder<boost::container::new_allocator<std::__1::unique_ptr<int,
       std::__1::default_delete<int> > >,
 boost::intrusive::rbtree_impl<boost::intrusive::bhtraits<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
       boost::container::tree_type_enum::red_black_tree, true>,
 boost::intrusive::rbtree_node_traits<void *, true>,
 boost::intrusive::link_mode_type::normal_link, boost::intrusive::dft_tag,
 3>, void,
 boost::container::value_to_node_compare<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
 boost::container::tree_type_enum::red_black_tree, true>,
       boost::intrusive::tree_value_compare<std::__1::unique_ptr<int,
 std::__1::default_delete<int> > *,
 std::__1::less<std::__1::unique_ptr<int, std::__1::default_delete<int> >
>, boost::move_detail::identity<std::__1::unique_ptr<int,
       std::__1::default_delete<int> > >, true> >, unsigned long, true,
 void> >::create_node<const std::__1::unique_ptr<int,
 std::__1::default_delete<int> > &>' requested here
          return m_holder.create_node(other.m_data);
                          ^
 ./boost_1_66_0/boost/intrusive/detail/node_cloner_disposer.hpp:65:42:
 note: in instantiation of member function
 'boost::container::container_detail::RecyclingCloner<boost::container::container_detail::node_alloc_holder<boost::container::new_allocator<std::__1::unique_ptr<int,
 std::__1::default_delete<int> > >,
 boost::intrusive::rbtree_impl<boost::intrusive::bhtraits<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
 boost::container::tree_type_enum::red_black_tree, true>,
       boost::intrusive::rbtree_node_traits<void *, true>,
 boost::intrusive::link_mode_type::normal_link, boost::intrusive::dft_tag,
 3>, void,
 boost::container::value_to_node_compare<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
 boost::container::tree_type_enum::red_black_tree, true>,
       boost::intrusive::tree_value_compare<std::__1::unique_ptr<int,
 std::__1::default_delete<int> > *,
 std::__1::less<std::__1::unique_ptr<int, std::__1::default_delete<int> >
>, boost::move_detail::identity<std::__1::unique_ptr<int,
       std::__1::default_delete<int> > >, true> >, unsigned long, true,
 void> >, true>::operator()' requested here
       node_ptr n = traits_->to_node_ptr(*base_t::get()(v));
                                          ^
 ./boost_1_66_0/boost/intrusive/rbtree_algorithms.hpp:59:20: note: in
 instantiation of member function
 'boost::intrusive::detail::node_cloner<boost::container::container_detail::RecyclingCloner<boost::container::container_detail::node_alloc_holder<boost::container::new_allocator<std::__1::unique_ptr<int,
       std::__1::default_delete<int> > >,
 boost::intrusive::rbtree_impl<boost::intrusive::bhtraits<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
       boost::container::tree_type_enum::red_black_tree, true>,
 boost::intrusive::rbtree_node_traits<void *, true>,
 boost::intrusive::link_mode_type::normal_link, boost::intrusive::dft_tag,
 3>, void,
 boost::container::value_to_node_compare<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
 boost::container::tree_type_enum::red_black_tree, true>,
       boost::intrusive::tree_value_compare<std::__1::unique_ptr<int,
 std::__1::default_delete<int> > *,
 std::__1::less<std::__1::unique_ptr<int, std::__1::default_delete<int> >
>, boost::move_detail::identity<std::__1::unique_ptr<int,
       std::__1::default_delete<int> > >, true> >, unsigned long, true,
 void> >, true>,
 boost::intrusive::bhtraits<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
       boost::container::tree_type_enum::red_black_tree, true>,
 boost::intrusive::rbtree_node_traits<void *, true>,
 boost::intrusive::link_mode_type::normal_link, boost::intrusive::dft_tag,
 3>,
       boost::intrusive::algo_types::RbTreeAlgorithms, false>::operator()'
 requested here
       node_ptr n = base_t::get()(p);
                    ^
 ./boost_1_66_0/boost/intrusive/bstree_algorithms.hpp:1943:55: note:
 (skipping 3 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see
 all)
          node_ptr insertion_point = target_sub_root = cloner(current);
                                                       ^
 ./boost_1_66_0/boost/intrusive/bstree.hpp:1040:27: note: in instantiation
 of function template specialization
 'boost::intrusive::rbtree_algorithms<boost::intrusive::rbtree_node_traits<void
 *, true>
>::clone<boost::intrusive::detail::node_cloner<boost::container::container_detail::RecyclingCloner<boost::container::container_detail::node_alloc_holder<boost::container::new_allocator<std::__1::unique_ptr<int,
       std::__1::default_delete<int> > >,
 boost::intrusive::rbtree_impl<boost::intrusive::bhtraits<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
       boost::container::tree_type_enum::red_black_tree, true>,
 boost::intrusive::rbtree_node_traits<void *, true>,
 boost::intrusive::link_mode_type::normal_link, boost::intrusive::dft_tag,
 3>, void,
 boost::container::value_to_node_compare<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
 boost::container::tree_type_enum::red_black_tree, true>,
       boost::intrusive::tree_value_compare<std::__1::unique_ptr<int,
 std::__1::default_delete<int> > *,
 std::__1::less<std::__1::unique_ptr<int, std::__1::default_delete<int> >
>, boost::move_detail::identity<std::__1::unique_ptr<int,
       std::__1::default_delete<int> > >, true> >, unsigned long, true,
 void> >, true>,
 boost::intrusive::bhtraits<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
       boost::container::tree_type_enum::red_black_tree, true>,
 boost::intrusive::rbtree_node_traits<void *, true>,
 boost::intrusive::link_mode_type::normal_link, boost::intrusive::dft_tag,
 3>,
       boost::intrusive::algo_types::RbTreeAlgorithms, false>,
 boost::intrusive::detail::node_disposer<boost::container::container_detail::allocator_destroyer<boost::container::new_allocator<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int>
>, void *, boost::container::tree_type_enum::red_black_tree, true> >
>,
 boost::intrusive::bhtraits<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
       boost::container::tree_type_enum::red_black_tree, true>,
 boost::intrusive::rbtree_node_traits<void *, true>,
 boost::intrusive::link_mode_type::normal_link, boost::intrusive::dft_tag,
 3>,
       boost::intrusive::algo_types::RbTreeAlgorithms> >' requested here
          node_algorithms::clone
                           ^
 ./boost_1_66_0/boost/intrusive/rbtree.hpp:240:18: note: in instantiation
 of function template specialization
 'boost::intrusive::bstree_impl<boost::intrusive::bhtraits<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
 boost::container::tree_type_enum::red_black_tree, true>,
       boost::intrusive::rbtree_node_traits<void *, true>,
 boost::intrusive::link_mode_type::normal_link, boost::intrusive::dft_tag,
 3>, void,
 boost::container::value_to_node_compare<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
 boost::container::tree_type_enum::red_black_tree, true>,
       boost::intrusive::tree_value_compare<std::__1::unique_ptr<int,
 std::__1::default_delete<int> > *,
 std::__1::less<std::__1::unique_ptr<int, std::__1::default_delete<int> >
>, boost::move_detail::identity<std::__1::unique_ptr<int,
       std::__1::default_delete<int> > >, true> >, unsigned long, true,
 boost::intrusive::algo_types::RbTreeAlgorithms,
 void>::clone_from<boost::container::container_detail::RecyclingCloner<boost::container::container_detail::node_alloc_holder<boost::container::new_allocator<std::__1::unique_ptr<int,
 std::__1::default_delete<int> > >,
 boost::intrusive::rbtree_impl<boost::intrusive::bhtraits<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
 boost::container::tree_type_enum::red_black_tree, true>,
       boost::intrusive::rbtree_node_traits<void *, true>,
 boost::intrusive::link_mode_type::normal_link, boost::intrusive::dft_tag,
 3>, void,
 boost::container::value_to_node_compare<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
 boost::container::tree_type_enum::red_black_tree, true>,
       boost::intrusive::tree_value_compare<std::__1::unique_ptr<int,
 std::__1::default_delete<int> > *,
 std::__1::less<std::__1::unique_ptr<int, std::__1::default_delete<int> >
>, boost::move_detail::identity<std::__1::unique_ptr<int,
       std::__1::default_delete<int> > >, true> >, unsigned long, true,
 void> >, true>,
 boost::container::container_detail::allocator_destroyer<boost::container::new_allocator<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
       boost::container::tree_type_enum::red_black_tree, true> > > >'
 requested here
    { tree_type::clone_from(BOOST_MOVE_BASE(tree_type, src), cloner,
 disposer); }
                  ^
 ./boost_1_66_0/boost/container/detail/tree.hpp:759:24: note: in
 instantiation of function template specialization
 'boost::intrusive::rbtree_impl<boost::intrusive::bhtraits<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
 boost::container::tree_type_enum::red_black_tree, true>,
       boost::intrusive::rbtree_node_traits<void *, true>,
 boost::intrusive::link_mode_type::normal_link, boost::intrusive::dft_tag,
 3>, void,
 boost::container::value_to_node_compare<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
 boost::container::tree_type_enum::red_black_tree, true>,
       boost::intrusive::tree_value_compare<std::__1::unique_ptr<int,
 std::__1::default_delete<int> > *,
 std::__1::less<std::__1::unique_ptr<int, std::__1::default_delete<int> >
>, boost::move_detail::identity<std::__1::unique_ptr<int,
       std::__1::default_delete<int> > >, true> >, unsigned long, true,
 void>::clone_from<boost::container::container_detail::RecyclingCloner<boost::container::container_detail::node_alloc_holder<boost::container::new_allocator<std::__1::unique_ptr<int,
 std::__1::default_delete<int> > >,
 boost::intrusive::rbtree_impl<boost::intrusive::bhtraits<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
 boost::container::tree_type_enum::red_black_tree, true>,
       boost::intrusive::rbtree_node_traits<void *, true>,
 boost::intrusive::link_mode_type::normal_link, boost::intrusive::dft_tag,
 3>, void,
 boost::container::value_to_node_compare<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
 boost::container::tree_type_enum::red_black_tree, true>,
       boost::intrusive::tree_value_compare<std::__1::unique_ptr<int,
 std::__1::default_delete<int> > *,
 std::__1::less<std::__1::unique_ptr<int, std::__1::default_delete<int> >
>, boost::move_detail::identity<std::__1::unique_ptr<int,
       std::__1::default_delete<int> > >, true> >, unsigned long, true,
 void> >, true>,
 boost::container::container_detail::allocator_destroyer<boost::container::new_allocator<boost::container::container_detail::tree_node<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, void *,
       boost::container::tree_type_enum::red_black_tree, true> > > >'
 requested here
          this->icont().clone_from
                        ^
 ./boost_1_66_0/boost/container/set.hpp:360:46: note: in instantiation of
 member function
 'boost::container::container_detail::tree<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >,
       boost::move_detail::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::container::new_allocator<std::__1::unique_ptr<int,
       std::__1::default_delete<int> > >,
 boost::container::tree_opt<boost::container::tree_type_enum::red_black_tree,
 true> >::operator=' requested here
    { return
 static_cast<set&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); }
                                              ^
 /home/brd/tmp/test.cpp:7:10: note: in instantiation of member function
 'boost::container::set<std::__1::unique_ptr<int,
 std::__1::default_delete<int> >, std::__1::less<std::__1::unique_ptr<int,
 std::__1::default_delete<int> > >,
       boost::container::new_allocator<std::__1::unique_ptr<int,
 std::__1::default_delete<int> > >,
 boost::container::tree_opt<boost::container::tree_type_enum::red_black_tree,
 true> >::operator=' requested here
     set2 = std::move(set1);
          ^
 /home/brd/soft/clang+llvm-5.0.0-linux-
 x86_64-ubuntu14.04/bin/../include/c++/v1/memory:2388:3: note: copy
 constructor is implicitly deleted because 'unique_ptr<int,
 std::__1::default_delete<int> >' has a user-declared move constructor
   unique_ptr(unique_ptr&& __u) noexcept
   ^
 1 error generated.
 }}}

-- 
Ticket URL: <https://svn.boost.org/trac10/boost/ticket/13405>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2018-01-17 17:40:45 UTC