diff --git a/doc/container.qbk b/doc/container.qbk index 6e00214..152e5f1 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1221,6 +1221,7 @@ use [*Boost.Container]? There are several reasons for that: * [@https://svn.boost.org/trac/boost/ticket/11856 Trac #11856 : ['"pool_resource.cpp error: declaration changes meaning"]]. * [@https://svn.boost.org/trac/boost/ticket/11866 Trac #11866 : ['"small_vector does not have range constructor"]]. * [@https://svn.boost.org/trac/boost/ticket/11867 Trac #11867 : ['"small_vector should have constructor and assignment operator taking other small_vector"]]. + * [@https://svn.boost.org/trac/boost/ticket/12014 Trac #12014 : ['"boost::container::set can not insert const (ref) range"]]. * [@https://github.com/boostorg/container/pull/33 GitHub #33: ['Make sure std::string constructor is available]]. [endsect] diff --git a/include/boost/container/detail/pair.hpp b/include/boost/container/detail/pair.hpp index 17766f3..134760e 100644 --- a/include/boost/container/detail/pair.hpp +++ b/include/boost/container/detail/pair.hpp @@ -317,6 +317,16 @@ struct is_class_or_union< ::boost::container::container_detail::pair > static const bool value = true; }; +template +struct is_class_or_union< std::pair > +//This specialization is needed to avoid instantiation of pair in +//is_class, and allow recursive maps. +{ + static const bool value = true; +}; + + + } //namespace move_detail{ diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 7ced4bb..0fd6097 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -50,6 +50,7 @@ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #include #endif +#include // other #include @@ -526,12 +527,12 @@ class tree const const_iterator end_it(this->cend()); if(unique_insertion){ for ( ; first != last; ++first){ - this->insert_unique(end_it, *first); + this->insert_unique_convertible(end_it, *first); } } else{ for ( ; first != last; ++first){ - this->insert_equal(end_it, *first); + this->insert_equal_convertible(end_it, *first); } } } @@ -555,7 +556,7 @@ class tree //for the constructor const const_iterator end_it(this->cend()); for ( ; first != last; ++first){ - this->insert_unique(end_it, *first); + this->insert_unique_convertible(end_it, *first); } } else{ @@ -983,19 +984,8 @@ class tree #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - iterator insert_unique(const_iterator hint, const value_type& v) - { - BOOST_ASSERT((priv_is_linked)(hint)); - insert_commit_data data; - std::pair ret = - this->insert_unique_check(hint, KeyOfValue()(v), data); - if(!ret.second) - return ret.first; - return this->insert_unique_commit(v, data); - } - template - iterator insert_unique(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v) + iterator insert_unique_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v) { BOOST_ASSERT((priv_is_linked)(hint)); insert_commit_data data; @@ -1006,6 +996,8 @@ class tree return this->insert_unique_commit(boost::forward(v), data); } + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_unique, value_type, iterator, this->insert_unique_convertible, const_iterator, const_iterator) + template void insert_unique(InputIterator first, InputIterator last) { @@ -1032,18 +1024,8 @@ class tree return ret; } - iterator insert_equal(const_iterator hint, const value_type& v) - { - BOOST_ASSERT((priv_is_linked)(hint)); - NodePtr tmp(AllocHolder::create_node(v)); - scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); - iterator ret(this->icont().insert_equal(hint.get(), *tmp)); - destroy_deallocator.release(); - return ret; - } - template - iterator insert_equal(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v) + iterator insert_equal_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v) { BOOST_ASSERT((priv_is_linked)(hint)); NodePtr tmp(AllocHolder::create_node(boost::forward(v))); @@ -1053,6 +1035,8 @@ class tree return ret; } + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_equal, value_type, iterator, this->insert_equal_convertible, const_iterator, const_iterator) + template void insert_equal(InputIterator first, InputIterator last) { diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp index 2e28e70..87cc183 100644 --- a/include/boost/container/map.hpp +++ b/include/boost/container/map.hpp @@ -596,7 +596,7 @@ class map //! Complexity: Logarithmic in general, but amortized constant if t //! is inserted right before p. iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x) - { return this->base_t::insert_unique(p, boost::move(x)); } + { return this->base_t::insert_unique_convertible(p, boost::move(x)); } //! Effects: Move constructs a new value from x if and only if there is //! no element in the container with key equivalent to the key of x. @@ -608,7 +608,7 @@ class map //! Complexity: Logarithmic in general, but amortized constant if t //! is inserted right before p. iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x) - { return this->base_t::insert_unique(p, boost::move(x)); } + { return this->base_t::insert_unique_convertible(p, boost::move(x)); } //! Effects: Inserts a copy of x in the container. //! p is a hint pointing to where the insert should start to search. @@ -617,7 +617,7 @@ class map //! //! Complexity: Logarithmic. iterator insert(const_iterator p, const nonconst_value_type& x) - { return this->base_t::insert_unique(p, x); } + { return this->base_t::insert_unique_convertible(p, x); } //! Effects: Inserts an element move constructed from x in the container. //! p is a hint pointing to where the insert should start to search. @@ -1291,7 +1291,7 @@ class multimap //! Complexity: Logarithmic in general, but amortized constant if t //! is inserted right before p. iterator insert(const_iterator p, const nonconst_value_type& x) - { return this->base_t::insert_equal(p, x); } + { return this->base_t::insert_equal_convertible(p, x); } //! Effects: Inserts a new value move constructed from x in the container. //! p is a hint pointing to where the insert should start to search. @@ -1302,7 +1302,7 @@ class multimap //! Complexity: Logarithmic in general, but amortized constant if t //! is inserted right before p. iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x) - { return this->base_t::insert_equal(p, boost::move(x)); } + { return this->base_t::insert_equal_convertible(p, boost::move(x)); } //! Effects: Inserts a new value move constructed from x in the container. //! p is a hint pointing to where the insert should start to search. @@ -1313,7 +1313,7 @@ class multimap //! Complexity: Logarithmic in general, but amortized constant if t //! is inserted right before p. iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x) - { return this->base_t::insert_equal(p, boost::move(x)); } + { return this->base_t::insert_equal_convertible(p, boost::move(x)); } //! Requires: first, last are not iterators into *this. //! diff --git a/test/map_test.hpp b/test/map_test.hpp index 79504d9..64893dd 100644 --- a/test/map_test.hpp +++ b/test/map_test.hpp @@ -79,6 +79,12 @@ int map_test_copyable(boost::container::container_detail::true_type) MyBoostMultiMap &boostmultimap = *pboostmultimap; MyStdMultiMap &stdmultimap = *pstdmultimap; + //Just to test move aware catch conversions + boostmap.insert(boostmap.cbegin(), boostmap.cend()); + boostmultimap.insert(boostmultimap.cbegin(), boostmultimap.cend()); + boostmap.insert(boostmap.begin(), boostmap.end()); + boostmultimap.insert(boostmultimap.begin(), boostmultimap.end()); + int i; for(i = 0; i < max; ++i){ { diff --git a/test/set_test.hpp b/test/set_test.hpp index 1ab8af5..0b1be22 100644 --- a/test/set_test.hpp +++ b/test/set_test.hpp @@ -65,6 +65,12 @@ int set_test_copyable(boost::container::container_detail::true_type) MyBoostMultiSet &boostmultiset = *pboostmultiset; MyStdMultiSet &stdmultiset = *pstdmultiset; + //Just to test move aware catch conversions + boostset.insert(boostset.cbegin(), boostset.cend()); + boostmultiset.insert(boostmultiset.cbegin(), boostmultiset.cend()); + boostset.insert(boostset.begin(), boostset.end()); + boostmultiset.insert(boostmultiset.begin(), boostmultiset.end()); + for(int i = 0; i < max; ++i){ IntType move_me(i); boostset.insert(boost::move(move_me));