diff --git a/include/boost/container/detail/addressof.hpp b/include/boost/container/detail/addressof.hpp index cc582c4..fedbdb9 100644 --- a/include/boost/container/detail/addressof.hpp +++ b/include/boost/container/detail/addressof.hpp @@ -25,12 +25,12 @@ namespace container { namespace container_detail { template -inline T* addressof(T& obj) +BOOST_CONTAINER_FORCEINLINE T* addressof(T& obj) { return static_cast( static_cast( const_cast( - &reinterpret_cast(obj) + &reinterpret_cast(obj) ))); } diff --git a/include/boost/container/detail/dispatch_uses_allocator.hpp b/include/boost/container/detail/dispatch_uses_allocator.hpp index cf2f2ba..fdf203c 100644 --- a/include/boost/container/detail/dispatch_uses_allocator.hpp +++ b/include/boost/container/detail/dispatch_uses_allocator.hpp @@ -280,9 +280,131 @@ typename container_detail::enable_if_and , Pair* p, BOOST_RV_REF_BEG Pair2 BOOST_RV_REF_END x) { (dispatch_uses_allocator)(construct_alloc, arg_alloc, p, ::boost::move(x.first), ::boost::move(x.second)); } -//template -//void dispatch_uses_allocator( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc -// , pair* p, piecewise_construct_t, tuple x, tuple y); + +//piecewise construction from boost::tuple +#define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE(N,M)\ +template< typename ConstructAlloc, typename ArgAlloc, class Pair \ + , template class BoostTuple \ + BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \ +typename container_detail::enable_if< container_detail::is_pair >::type\ + dispatch_uses_allocator( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t\ + , BoostTuple p\ + , BoostTuple q)\ +{\ + (void)p; (void)q;\ + (dispatch_uses_allocator)\ + (construct_alloc, arg_alloc, container_detail::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_TMPL_GET##N);\ + BOOST_TRY{\ + (dispatch_uses_allocator)\ + (construct_alloc, arg_alloc, container_detail::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_TMPL_GETQ##M);\ + }\ + BOOST_CATCH(...) {\ + allocator_traits::destroy(construct_alloc, container_detail::addressof(pair->first));\ + BOOST_RETHROW\ + }\ + BOOST_CATCH_END\ +}\ +// +BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE) +#undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE + +//piecewise construction from Std Tuple +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + template< typename ConstructAlloc, typename ArgAlloc, class Pair + , template class Tuple, class... Args1, class... Args2, size_t... Indexes1, size_t... Indexes2> + void dispatch_uses_allocator_index( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair + , Tuple& t1, Tuple& t2, index_tuple, index_tuple) + { + (void)t1; (void)t2; + (dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(pair->first), ::boost::forward(get(t1))...); + BOOST_TRY{ + (dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(pair->second), ::boost::forward(get(t2))...); + } + BOOST_CATCH(...){ + allocator_traits::destroy(construct_alloc, container_detail::addressof(pair->first)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + template< typename ConstructAlloc, typename ArgAlloc, class Pair + , template class Tuple, class... Args1, class... Args2> + typename container_detail::enable_if< container_detail::is_pair >::type + dispatch_uses_allocator( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t + , Tuple t1, Tuple t2) + { + (dispatch_uses_allocator_index)( construct_alloc, arg_alloc, pair, t1, t2 + , typename build_number_seq::type() + , typename build_number_seq::type()); + } + +#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 520) + + //MSVC 2010 tuple implementation + #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE(N,M)\ + template< typename ConstructAlloc, typename ArgAlloc, class Pair\ + , template class StdTuple\ + BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \ + typename container_detail::enable_if< container_detail::is_pair >::type\ + dispatch_uses_allocator(ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t\ + , StdTuple p\ + , StdTuple q)\ + {\ + (void)p; (void)q;\ + (dispatch_uses_allocator)\ + (construct_alloc, arg_alloc, container_detail::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\ + BOOST_TRY{\ + (dispatch_uses_allocator)\ + (construct_alloc, arg_alloc, container_detail::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\ + }\ + BOOST_CATCH(...) {\ + allocator_traits::destroy(construct_alloc, container_detail::addressof(pair->first));\ + BOOST_RETHROW\ + }\ + BOOST_CATCH_END\ + }\ + // + BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE) + #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE + +#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540) + #if _VARIADIC_MAX >= 9 + #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT 9 + #else + #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT BOOST_MOVE_ADD(_VARIADIC_MAX, 1) + #endif + + //MSVC 2012 tuple implementation + #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE(N,M)\ + template< typename ConstructAlloc, typename ArgAlloc, class Pair\ + , template class StdTuple \ + BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \ + typename container_detail::enable_if< container_detail::is_pair >::type\ + dispatch_uses_allocator\ + ( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc, Pair* pair, piecewise_construct_t\ + , StdTuple p\ + , StdTuple q)\ + {\ + (void)p; (void)q;\ + (dispatch_uses_allocator)\ + (construct_alloc, arg_alloc, container_detail::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\ + BOOST_TRY{\ + (dispatch_uses_allocator)\ + (construct_alloc, arg_alloc, container_detail::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\ + }\ + BOOST_CATCH(...) {\ + allocator_traits::destroy(construct_alloc, container_detail::addressof(pair->first));\ + BOOST_RETHROW\ + }\ + BOOST_CATCH_END\ + }\ + // + BOOST_MOVE_ITER2D_0TOMAX(BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE) + #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE + #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT + +#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) } //namespace container_detail diff --git a/include/boost/container/detail/workaround.hpp b/include/boost/container/detail/workaround.hpp index 9b74d85..64ecd6f 100644 --- a/include/boost/container/detail/workaround.hpp +++ b/include/boost/container/detail/workaround.hpp @@ -49,6 +49,10 @@ #define BOOST_CONTAINER_FALLTHOUGH BOOST_FALLTHOUGH; #endif +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) || (defined(BOOST_MSVC) && (BOOST_MSVC == 1700 || BOOST_MSVC == 1600)) +#define BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE +#endif + //Macros for documentation purposes. For code, expands to the argument #define BOOST_CONTAINER_IMPDEF(TYPE) TYPE #define BOOST_CONTAINER_SEEDOC(TYPE) TYPE diff --git a/test/scoped_allocator_adaptor_test.cpp b/test/scoped_allocator_adaptor_test.cpp index 0a6d71e..d21afa4 100644 --- a/test/scoped_allocator_adaptor_test.cpp +++ b/test/scoped_allocator_adaptor_test.cpp @@ -15,10 +15,16 @@ // move #include #include +//boost +#include // std #include #include +#if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE) +#include +#endif + //test #include @@ -894,7 +900,81 @@ int main() BOOST_TEST(dummy.second.value == 0); dummy.~MarkTypePair(); } - + #if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE) + //Check construction with 0 user arguments and Std tuple + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>()); + BOOST_TEST(dummy.first.construction_type == NotUsesAllocator); + BOOST_TEST(dummy.second.construction_type == NotUsesAllocator); + BOOST_TEST(dummy.first.value == 0); + BOOST_TEST(dummy.second.value == 0); + dummy.~MarkTypePair(); + } + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>()); + BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix); + BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix); + BOOST_TEST(dummy.first.value == 0); + BOOST_TEST(dummy.second.value == 0); + dummy.~MarkTypePair(); + } + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>()); + BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix); + BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix); + BOOST_TEST(dummy.first.value == 0); + BOOST_TEST(dummy.second.value == 0); + dummy.~MarkTypePair(); + } + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>()); + BOOST_TEST(dummy.first.construction_type == NotUsesAllocator); + BOOST_TEST(dummy.second.construction_type == NotUsesAllocator); + BOOST_TEST(dummy.first.value == 0); + BOOST_TEST(dummy.second.value == 0); + dummy.~MarkTypePair(); + } + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>()); + BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix); + BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix); + BOOST_TEST(dummy.first.value == 0); + BOOST_TEST(dummy.second.value == 0); + dummy.~MarkTypePair(); + } + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>()); + BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix); + BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix); + BOOST_TEST(dummy.first.value == 0); + BOOST_TEST(dummy.second.value == 0); + dummy.~MarkTypePair(); + } + #endif //BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE //Check construction with 1 user arguments for each pair { typedef ::allocator_argument_tester MarkType; @@ -932,6 +1012,82 @@ int main() BOOST_TEST(dummy.second.value == 2); dummy.~MarkTypePair(); } + //Check construction with 1 user arguments for each pair and Boost tuple + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, boost::tuple(1), boost::tuple(1)); + BOOST_TEST(dummy.first.construction_type == NotUsesAllocator); + BOOST_TEST(dummy.second.construction_type == NotUsesAllocator); + BOOST_TEST(dummy.first.value == 1); + BOOST_TEST(dummy.second.value == 1); + dummy.~MarkTypePair(); + } + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, boost::tuple(1), boost::tuple(1)); + BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix); + BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix); + BOOST_TEST(dummy.first.value == 1); + BOOST_TEST(dummy.second.value == 1); + dummy.~MarkTypePair(); + } + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, boost::tuple(2), boost::tuple(2)); + BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix); + BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix); + BOOST_TEST(dummy.first.value == 2); + BOOST_TEST(dummy.second.value == 2); + dummy.~MarkTypePair(); + } + #if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE) + //Check construction with 1 user arguments for each pair and Boost tuple + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, std::tuple(1), std::tuple(1)); + BOOST_TEST(dummy.first.construction_type == NotUsesAllocator); + BOOST_TEST(dummy.second.construction_type == NotUsesAllocator); + BOOST_TEST(dummy.first.value == 1); + BOOST_TEST(dummy.second.value == 1); + dummy.~MarkTypePair(); + } + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, std::tuple(1), std::tuple(1)); + BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix); + BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix); + BOOST_TEST(dummy.first.value == 1); + BOOST_TEST(dummy.second.value == 1); + dummy.~MarkTypePair(); + } + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, std::tuple(2), std::tuple(2)); + BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix); + BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix); + BOOST_TEST(dummy.first.value == 2); + BOOST_TEST(dummy.second.value == 2); + dummy.~MarkTypePair(); + } + #endif //BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE //Check construction with pair copy construction { typedef ::allocator_argument_tester MarkType; @@ -1099,6 +1255,82 @@ int main() BOOST_TEST(dummy.second.value == 2); dummy.~MarkTypePair(); } + //Check construction with 0/1 arguments for each pair and Boost tuple + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, boost::tuple<>(), boost::tuple(1)); + BOOST_TEST(dummy.first.construction_type == NotUsesAllocator); + BOOST_TEST(dummy.second.construction_type == NotUsesAllocator); + BOOST_TEST(dummy.first.value == 0); + BOOST_TEST(dummy.second.value == 1); + dummy.~MarkTypePair(); + } + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, boost::tuple(1), boost::tuple<>()); + BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix); + BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix); + BOOST_TEST(dummy.first.value == 1); + BOOST_TEST(dummy.second.value == 0); + dummy.~MarkTypePair(); + } + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, boost::tuple<>(), boost::tuple(2)); + BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix); + BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix); + BOOST_TEST(dummy.first.value == 0); + BOOST_TEST(dummy.second.value == 2); + dummy.~MarkTypePair(); + } + #if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE) + //Check construction with 0/1 arguments for each pair and Boost tuple + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple(1)); + BOOST_TEST(dummy.first.construction_type == NotUsesAllocator); + BOOST_TEST(dummy.second.construction_type == NotUsesAllocator); + BOOST_TEST(dummy.first.value == 0); + BOOST_TEST(dummy.second.value == 1); + dummy.~MarkTypePair(); + } + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, std::tuple(1), std::tuple<>()); + BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix); + BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix); + BOOST_TEST(dummy.first.value == 1); + BOOST_TEST(dummy.second.value == 0); + dummy.~MarkTypePair(); + } + { + typedef ::allocator_argument_tester MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple(2)); + BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix); + BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix); + BOOST_TEST(dummy.first.value == 0); + BOOST_TEST(dummy.second.value == 2); + dummy.~MarkTypePair(); + } + #endif //BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE } }