Skip to content

Commit a6a41e2

Browse files
committed
FIxes #297 ("flat_map::try_emplace does not compile if allocator has construct")
1 parent 1f54321 commit a6a41e2

File tree

3 files changed

+80
-39
lines changed

3 files changed

+80
-39
lines changed

doc/container.qbk

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,13 @@ use [*Boost.Container]? There are several reasons for that:
14211421

14221422
[section:release_notes Release Notes]
14231423

1424+
[section:release_notes_boost_1_88_00 Boost 1.88 Release]
1425+
1426+
* Fixed bugs/issues:
1427+
* [@https://github.com/boostorg/container/issues/297 GitHub #297: ['"flat_map::try_emplace does not compile if allocator has construct"]].
1428+
1429+
[endsect]
1430+
14241431
[section:release_notes_boost_1_87_00 Boost 1.87 Release]
14251432

14261433
* Added [classref boost::container::stored_size stored_size] option to

include/boost/container/allocator_traits.hpp

Lines changed: 58 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -94,23 +94,6 @@ BOOST_CONTAINER_FORCEINLINE void construct_type(T *p, BOOST_FWD_REF(Args) ...arg
9494
::new((void*)p, boost_container_new_t()) T(::boost::forward<Args>(args)...);
9595
}
9696

97-
template < class Pair, class KeyType, class ... Args>
98-
typename dtl::enable_if< dtl::is_pair<Pair>, void >::type
99-
construct_type
100-
(Pair* p, try_emplace_t, BOOST_FWD_REF(KeyType) k, BOOST_FWD_REF(Args) ...args)
101-
{
102-
construct_type(dtl::addressof(p->first), ::boost::forward<KeyType>(k));
103-
BOOST_CONTAINER_TRY{
104-
construct_type(dtl::addressof(p->second), ::boost::forward<Args>(args)...);
105-
}
106-
BOOST_CONTAINER_CATCH(...) {
107-
typedef typename Pair::first_type first_type;
108-
dtl::addressof(p->first)->~first_type();
109-
BOOST_CONTAINER_RETHROW
110-
}
111-
BOOST_CONTAINER_CATCH_END
112-
}
113-
11497
#else
11598

11699
#define BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPEJ(N) \
@@ -125,32 +108,12 @@ construct_type(T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
125108
BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPEJ)
126109
#undef BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPEJ
127110

128-
#define BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPE(N) \
129-
template < class Pair, class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
130-
typename dtl::enable_if< dtl::is_pair<Pair>, void >::type construct_type\
131-
(Pair* p, try_emplace_t, BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
132-
{\
133-
construct_type(dtl::addressof(p->first), ::boost::forward<KeyType>(k));\
134-
BOOST_CONTAINER_TRY{\
135-
construct_type(dtl::addressof(p->second) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
136-
}\
137-
BOOST_CONTAINER_CATCH(...) {\
138-
typedef typename Pair::first_type first_type;\
139-
dtl::addressof(p->first)->~first_type();\
140-
BOOST_CONTAINER_RETHROW\
141-
}\
142-
BOOST_CONTAINER_CATCH_END\
143-
}\
144-
//
145-
BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPE)
146-
#undef BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPE
147-
148111
#endif
149112

150113
template<class T>
151114
inline
152115
typename dtl::enable_if<dtl::is_pair<T>, void >::type
153-
construct_type(T* p)
116+
construct_type(T* p)
154117
{
155118
dtl::construct_type(dtl::addressof(p->first));
156119
BOOST_CONTAINER_TRY{
@@ -164,7 +127,6 @@ construct_type(T* p)
164127
BOOST_CONTAINER_CATCH_END
165128
}
166129

167-
168130
template<class T, class U>
169131
inline
170132
typename dtl::enable_if_c
@@ -509,6 +471,25 @@ struct allocator_traits
509471
}
510472
#endif
511473

474+
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
475+
476+
template < class Pair, class KeyType, class ... Args>
477+
static typename dtl::enable_if< dtl::is_pair<Pair>, void >::type construct
478+
(Allocator & a, Pair* p, try_emplace_t, BOOST_FWD_REF(KeyType) k, BOOST_FWD_REF(Args) ...args)
479+
{
480+
allocator_traits::construct(a, dtl::addressof(p->first), ::boost::forward<KeyType>(k));
481+
BOOST_CONTAINER_TRY{
482+
allocator_traits::construct(a, dtl::addressof(p->second), ::boost::forward<Args>(args)...);
483+
}
484+
BOOST_CONTAINER_CATCH(...) {
485+
typedef typename Pair::first_type first_type;
486+
dtl::addressof(p->first)->~first_type();
487+
BOOST_CONTAINER_RETHROW
488+
}
489+
BOOST_CONTAINER_CATCH_END
490+
}
491+
#endif
492+
512493
//! <b>Returns</b>: <code>a.storage_is_unpropagable(p)</code> if is_partially_propagable::value is true; otherwise,
513494
//! <code>false</code>.
514495
inline static bool storage_is_unpropagable(const Allocator &a, pointer p) BOOST_NOEXCEPT_OR_NOTHROW
@@ -582,6 +563,22 @@ struct allocator_traits
582563
inline static void priv_construct(dtl::true_type, Allocator &a, T *p, BOOST_FWD_REF(Args) ...args)
583564
{ a.construct( p, ::boost::forward<Args>(args)...); }
584565

566+
template<class T, class KeyType, class ...Args>
567+
inline static typename dtl::enable_if< dtl::is_pair<T>, void >::type
568+
priv_construct(dtl::true_type, Allocator &a, T *p, try_emplace_t, BOOST_FWD_REF(KeyType) k, BOOST_FWD_REF(Args) ...args)
569+
{
570+
a.construct(dtl::addressof(p->first), ::boost::forward<KeyType>(k));
571+
BOOST_CONTAINER_TRY{
572+
a.construct(dtl::addressof(p->second), ::boost::forward<Args>(args)...);
573+
}
574+
BOOST_CONTAINER_CATCH(...) {
575+
typedef typename T::first_type first_type;
576+
dtl::addressof(p->first)->~first_type();
577+
BOOST_CONTAINER_RETHROW
578+
}
579+
BOOST_CONTAINER_CATCH_END
580+
}
581+
585582
template<class T, class ...Args>
586583
inline static void priv_construct(dtl::false_type, Allocator &, T *p, BOOST_FWD_REF(Args) ...args)
587584
{ dtl::construct_type(p, ::boost::forward<Args>(args)...); }
@@ -600,6 +597,28 @@ struct allocator_traits
600597
dtl::bool_<value> flag;\
601598
(priv_construct)(flag, a, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
602599
}\
600+
\
601+
//
602+
BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL)
603+
#undef BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL
604+
605+
#define BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL(N) \
606+
template<class T, class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
607+
inline static typename dtl::enable_if< dtl::is_pair<T>, void >::type\
608+
construct(Allocator &a, T *p, try_emplace_t, BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
609+
{\
610+
allocator_traits::construct(a, dtl::addressof(p->first), ::boost::forward<KeyType>(k));\
611+
BOOST_CONTAINER_TRY{\
612+
allocator_traits::construct(a, dtl::addressof(p->second) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
613+
}\
614+
BOOST_CONTAINER_CATCH(...) {\
615+
typedef typename T::first_type first_type;\
616+
dtl::addressof(p->first)->~first_type();\
617+
BOOST_CONTAINER_RETHROW\
618+
}\
619+
BOOST_CONTAINER_CATCH_END\
620+
}\
621+
\
603622
//
604623
BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL)
605624
#undef BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL

test/allocator_traits_test.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <boost/container/allocator_traits.hpp>
1212
#include <boost/container/detail/type_traits.hpp>
1313
#include <boost/container/detail/function_detector.hpp>
14+
#include <boost/container/detail/pair.hpp>
1415
#include <boost/move/utility_core.hpp>
1516
#include <memory>
1617
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
@@ -420,6 +421,20 @@ int main()
420421
SAllocTraits::construct(s_alloc, &c, 0, 1, 2);
421422
BOOST_TEST(!c.copymoveconstructed() && !c.moved());
422423
}
424+
425+
{
426+
boost::container::dtl::pair<copymovable, copymovable> cp;
427+
copymovable k(99, 100, 101);
428+
SAllocTraits::construct(s_alloc, &cp, boost::container::try_emplace_t(), boost::move(k), 1, 2, 3);
429+
BOOST_TEST(cp.first.moved() && !cp.second.copymoveconstructed() && !cp.second.moved());
430+
}
431+
{
432+
boost::container::dtl::pair<copymovable, copymovable> cp;
433+
copymovable k(99, 100, 101);
434+
CAllocTraits::construct(c_alloc, &cp, boost::container::try_emplace_t(), boost::move(k), 1, 2, 3);
435+
BOOST_TEST(cp.first.moved() && !cp.second.copymoveconstructed() && !cp.second.moved());
436+
}
437+
423438
//storage_is_unpropagable
424439
{
425440
SAlloc s_alloc2;

0 commit comments

Comments
 (0)