Index: libcxx/include/memory =================================================================== --- libcxx/include/memory +++ libcxx/include/memory @@ -1459,23 +1459,18 @@ #else // _LIBCPP_CXX03_LANG -#ifndef _LIBCPP_HAS_NO_VARIADICS - -template -struct __has_construct - : false_type -{ -}; - -#else // _LIBCPP_HAS_NO_VARIADICS +template +struct __has_construct : std::false_type {}; template -struct __has_construct - : false_type -{ -}; - -#endif // _LIBCPP_HAS_NO_VARIADICS +struct __has_construct<_Alloc, _Pointer, _Args, typename enable_if< + is_same + < + decltype(_VSTD::declval<_Alloc>().construct(_VSTD::declval<_Pointer>(), + _VSTD::declval<_Args>())), + void + >::value +>::type> : std::true_type {}; template struct __has_destroy @@ -1570,9 +1565,10 @@ } template _LIBCPP_INLINE_VISIBILITY - static void construct(allocator_type&, _Tp* __p, const _A0& __a0) + static void construct(allocator_type& __a, _Tp* __p, const _A0& __a0) { - ::new ((void*)__p) _Tp(__a0); + __construct(__has_construct(), + __a, __p, __a0); } template _LIBCPP_INLINE_VISIBILITY @@ -1720,6 +1716,19 @@ { ::new ((void*)__p) _Tp(_VSTD::forward<_Args>(__args)...); } +#else // _LIBCPP_HAS_NO_VARIADICS + template + _LIBCPP_INLINE_VISIBILITY + static void __construct(true_type, allocator_type& __a, _Tp* __p, + const _A0& __a0) + {__a.construct(__p, __a0);} + template + _LIBCPP_INLINE_VISIBILITY + static void __construct(false_type, allocator_type&, _Tp* __p, + const _A0& __a0) + { + ::new ((void*)__p) _Tp(__a0); + } #endif // _LIBCPP_HAS_NO_VARIADICS template Index: libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter.pass.cpp =================================================================== --- libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter.pass.cpp +++ libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter.pass.cpp @@ -116,9 +116,37 @@ } void test_ctor_under_alloc() { -#if TEST_STD_VER >= 11 int arr1[] = {42}; int arr2[] = {1, 101, 42}; + { + typedef std::vector > C; + typedef C::allocator_type Alloc; + { + Alloc::construct_called = false; + C v(arr1, arr1 + 1); + assert(Alloc::construct_called); + } + { + Alloc::construct_called = false; + C v(arr2, arr2 + 3); + assert(Alloc::construct_called); + } + } + { + typedef std::vector > C; + typedef C::allocator_type Alloc; + { + Alloc::construct_called = false; + C v(arr1, arr1 + 1); + assert(Alloc::construct_called); + } + { + Alloc::construct_called = false; + C v(arr2, arr2 + 3); + assert(Alloc::construct_called); + } + } +#if TEST_STD_VER >= 11 { using C = TCT::vector<>; using T = typename C::value_type; Index: libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp =================================================================== --- libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp +++ libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp @@ -129,9 +129,39 @@ } void test_ctor_under_alloc() { -#if TEST_STD_VER >= 11 int arr1[] = {42}; int arr2[] = {1, 101, 42}; + { + typedef std::vector > C; + typedef C::allocator_type Alloc; + Alloc a; + { + Alloc::construct_called = false; + C v(arr1, arr1 + 1, a); + assert(Alloc::construct_called); + } + { + Alloc::construct_called = false; + C v(arr2, arr2 + 3, a); + assert(Alloc::construct_called); + } + } + { + typedef std::vector > C; + typedef C::allocator_type Alloc; + Alloc a; + { + Alloc::construct_called = false; + C v(arr1, arr1 + 1, a); + assert(Alloc::construct_called); + } + { + Alloc::construct_called = false; + C v(arr2, arr2 + 3, a); + assert(Alloc::construct_called); + } + } +#if TEST_STD_VER >= 11 { using C = TCT::vector<>; using T = typename C::value_type; Index: libcxx/test/support/min_allocator.h =================================================================== --- libcxx/test/support/min_allocator.h +++ libcxx/test/support/min_allocator.h @@ -14,6 +14,7 @@ #include #include #include +#include #include "test_macros.h" @@ -131,6 +132,57 @@ friend bool operator!=(malloc_allocator x, malloc_allocator y) {return !(x == y);} }; +template +struct cpp03_allocator : bare_allocator +{ + typedef T value_type; + typedef value_type* pointer; + + static bool construct_called; + + void construct(pointer p, const value_type& val) + { + ::new(p) value_type(val); + construct_called = true; + } + + std::size_t max_size() const + { + return UINT_MAX / sizeof(T); + } +}; +template bool cpp03_allocator::construct_called = false; + +template +struct cpp03_overload_allocator : bare_allocator +{ + typedef T value_type; + typedef value_type* pointer; + + static bool construct_called; + + void construct(pointer p, const value_type& val) + { + construct(p, val, std::is_class()); + } + void construct(pointer p, const value_type& val, std::true_type) + { + ::new(p) value_type(val); + construct_called = true; + } + void construct(pointer p, const value_type& val, std::false_type) + { + ::new(p) value_type(val); + construct_called = true; + } + + std::size_t max_size() const + { + return UINT_MAX / sizeof(T); + } +}; +template bool cpp03_overload_allocator::construct_called = false; + #if TEST_STD_VER >= 11