diff --git a/doc/container.qbk b/doc/container.qbk index f576120e..4c62c326 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1421,6 +1421,13 @@ use [*Boost.Container]? There are several reasons for that: [section:release_notes Release Notes] +[section:release_notes_boost_1_88_00 Boost 1.88 Release] + +* Fixed bugs/issues: + * [@https://github.com/boostorg/container/issues/297 GitHub #297: ['"flat_map::try_emplace does not compile if allocator has construct"]]. + +[endsect] + [section:release_notes_boost_1_87_00 Boost 1.87 Release] * Added [classref boost::container::stored_size stored_size] option to diff --git a/include/boost/container/allocator_traits.hpp b/include/boost/container/allocator_traits.hpp index 6a385cce..0d65d71f 100644 --- a/include/boost/container/allocator_traits.hpp +++ b/include/boost/container/allocator_traits.hpp @@ -94,23 +94,6 @@ BOOST_CONTAINER_FORCEINLINE void construct_type(T *p, BOOST_FWD_REF(Args) ...arg ::new((void*)p, boost_container_new_t()) T(::boost::forward(args)...); } -template < class Pair, class KeyType, class ... Args> -typename dtl::enable_if< dtl::is_pair, void >::type -construct_type - (Pair* p, try_emplace_t, BOOST_FWD_REF(KeyType) k, BOOST_FWD_REF(Args) ...args) -{ - construct_type(dtl::addressof(p->first), ::boost::forward(k)); - BOOST_CONTAINER_TRY{ - construct_type(dtl::addressof(p->second), ::boost::forward(args)...); - } - BOOST_CONTAINER_CATCH(...) { - typedef typename Pair::first_type first_type; - dtl::addressof(p->first)->~first_type(); - BOOST_CONTAINER_RETHROW - } - BOOST_CONTAINER_CATCH_END -} - #else #define BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPEJ(N) \ @@ -125,32 +108,12 @@ construct_type(T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPEJ) #undef BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPEJ -#define BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPE(N) \ -template < class Pair, class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\ -typename dtl::enable_if< dtl::is_pair, void >::type construct_type\ - (Pair* p, try_emplace_t, BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ -{\ - construct_type(dtl::addressof(p->first), ::boost::forward(k));\ - BOOST_CONTAINER_TRY{\ - construct_type(dtl::addressof(p->second) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ - }\ - BOOST_CONTAINER_CATCH(...) {\ - typedef typename Pair::first_type first_type;\ - dtl::addressof(p->first)->~first_type();\ - BOOST_CONTAINER_RETHROW\ - }\ - BOOST_CONTAINER_CATCH_END\ -}\ -// -BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPE) -#undef BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPE - #endif template inline typename dtl::enable_if, void >::type -construct_type(T* p) + construct_type(T* p) { dtl::construct_type(dtl::addressof(p->first)); BOOST_CONTAINER_TRY{ @@ -164,7 +127,6 @@ construct_type(T* p) BOOST_CONTAINER_CATCH_END } - template inline typename dtl::enable_if_c @@ -509,6 +471,25 @@ struct allocator_traits } #endif + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + template < class Pair, class KeyType, class ... Args> + static typename dtl::enable_if< dtl::is_pair, void >::type construct + (Allocator & a, Pair* p, try_emplace_t, BOOST_FWD_REF(KeyType) k, BOOST_FWD_REF(Args) ...args) + { + allocator_traits::construct(a, dtl::addressof(p->first), ::boost::forward(k)); + BOOST_CONTAINER_TRY{ + allocator_traits::construct(a, dtl::addressof(p->second), ::boost::forward(args)...); + } + BOOST_CONTAINER_CATCH(...) { + typedef typename Pair::first_type first_type; + dtl::addressof(p->first)->~first_type(); + BOOST_CONTAINER_RETHROW + } + BOOST_CONTAINER_CATCH_END + } + #endif + //! Returns: a.storage_is_unpropagable(p) if is_partially_propagable::value is true; otherwise, //! false. inline static bool storage_is_unpropagable(const Allocator &a, pointer p) BOOST_NOEXCEPT_OR_NOTHROW @@ -582,6 +563,22 @@ struct allocator_traits inline static void priv_construct(dtl::true_type, Allocator &a, T *p, BOOST_FWD_REF(Args) ...args) { a.construct( p, ::boost::forward(args)...); } + template + inline static typename dtl::enable_if< dtl::is_pair, void >::type + priv_construct(dtl::true_type, Allocator &a, T *p, try_emplace_t, BOOST_FWD_REF(KeyType) k, BOOST_FWD_REF(Args) ...args) + { + a.construct(dtl::addressof(p->first), ::boost::forward(k)); + BOOST_CONTAINER_TRY{ + a.construct(dtl::addressof(p->second), ::boost::forward(args)...); + } + BOOST_CONTAINER_CATCH(...) { + typedef typename T::first_type first_type; + dtl::addressof(p->first)->~first_type(); + BOOST_CONTAINER_RETHROW + } + BOOST_CONTAINER_CATCH_END + } + template inline static void priv_construct(dtl::false_type, Allocator &, T *p, BOOST_FWD_REF(Args) ...args) { dtl::construct_type(p, ::boost::forward(args)...); } @@ -600,6 +597,28 @@ struct allocator_traits dtl::bool_ flag;\ (priv_construct)(flag, a, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ }\ + \ + // + BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL) + #undef BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL + + #define BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL(N) \ + template\ + inline static typename dtl::enable_if< dtl::is_pair, void >::type\ + construct(Allocator &a, T *p, try_emplace_t, BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + {\ + allocator_traits::construct(a, dtl::addressof(p->first), ::boost::forward(k));\ + BOOST_CONTAINER_TRY{\ + allocator_traits::construct(a, dtl::addressof(p->second) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + }\ + BOOST_CONTAINER_CATCH(...) {\ + typedef typename T::first_type first_type;\ + dtl::addressof(p->first)->~first_type();\ + BOOST_CONTAINER_RETHROW\ + }\ + BOOST_CONTAINER_CATCH_END\ + }\ + \ // BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL) #undef BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL diff --git a/test/allocator_traits_test.cpp b/test/allocator_traits_test.cpp index 494b894e..89cd714c 100644 --- a/test/allocator_traits_test.cpp +++ b/test/allocator_traits_test.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) @@ -420,6 +421,20 @@ int main() SAllocTraits::construct(s_alloc, &c, 0, 1, 2); BOOST_TEST(!c.copymoveconstructed() && !c.moved()); } + + { + boost::container::dtl::pair cp; + copymovable k(99, 100, 101); + SAllocTraits::construct(s_alloc, &cp, boost::container::try_emplace_t(), boost::move(k), 1, 2, 3); + BOOST_TEST(cp.first.moved() && !cp.second.copymoveconstructed() && !cp.second.moved()); + } + { + boost::container::dtl::pair cp; + copymovable k(99, 100, 101); + CAllocTraits::construct(c_alloc, &cp, boost::container::try_emplace_t(), boost::move(k), 1, 2, 3); + BOOST_TEST(cp.first.moved() && !cp.second.copymoveconstructed() && !cp.second.moved()); + } + //storage_is_unpropagable { SAlloc s_alloc2;