EricWF updated this revision to Diff 63636. EricWF added a comment. Add correct tests.
http://reviews.llvm.org/D22255 Files: include/memory include/type_traits include/vector test/libcxx/utilities/memory/allocator.traits/__is_alloc_constructible.pass.cpp test/std/containers/sequences/vector/tagging_allocator_instantiation.pass.cpp test/support/tagging_allocator.hpp
Index: test/support/tagging_allocator.hpp =================================================================== --- /dev/null +++ test/support/tagging_allocator.hpp @@ -0,0 +1,125 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef TAGGING_ALLOCATOR_HPP +#define TAGGING_ALLOCATOR_HPP + +# include <cstdlib> +# include <cassert> +# include <new> + +#include "test_macros.h" +struct Tag { }; + +template<typename T> + class TaggingAllocator + { + public: + using value_type = T; + + TaggingAllocator() = default; + + template<typename U> + TaggingAllocator(const TaggingAllocator<U>&) { } + + T* + allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); } + + void + deallocate(T* p, std::size_t n) { std::allocator<T>{}.deallocate(p, n); } + + template<typename U, typename... Args> + + auto construct(U* p, Args&&... args) -> + decltype((void)::new((void*)p) U(Tag{}, std::forward<Args>(args)...)) + { ::new((void*)p) U(Tag{}, std::forward<Args>(args)...); } + + template<typename U, typename... Args> + auto destroy(U* p) -> decltype((void)p->~U()) { p->~U(); } + }; + +template<typename T, typename U> + bool + operator==(const TaggingAllocator<T>&, const TaggingAllocator<U>&) + { return true; } + +template<typename T, typename U> + bool + operator!=(const TaggingAllocator<T>&, const TaggingAllocator<U>&) + { return false; } + +template <class ...Args> +struct TaggedValueType +{ + // All constructors must be passed the Tag type. + + // DefaultInsertable into vector<X, TaggingAllocator<X>>, + explicit TaggedValueType(Tag) { } + // CopyInsertable into vector<X, TaggingAllocator<X>>, + TaggedValueType(Tag, const TaggedValueType&) { } + // MoveInsertable into vector<X, TaggingAllocator<X>>, and + TaggedValueType(Tag, TaggedValueType&&) { } + + // EmplaceConstructible into vector<X, TaggingAllocator<X>> from args. + explicit TaggedValueType(Tag, Args...) { } + + // not DefaultConstructible, CopyConstructible or MoveConstructible. + TaggedValueType() = delete; + TaggedValueType(const TaggedValueType&) = delete; + TaggedValueType(TaggedValueType&&) = delete; + + // CopyAssignable. + TaggedValueType& operator=(const TaggedValueType&) { return *this; } + + // MoveAssignable. + TaggedValueType& operator=(TaggedValueType&&) { return *this; } + +private: + // Not Destructible. + ~TaggedValueType() { } + + // Erasable from vector<X, TaggingAllocator<X>>. + template <class T> + friend class TaggingAllocator; +}; + + +template <> +struct TaggedValueType<> +{ + // All constructors must be passed the Tag type. + + // DefaultInsertable into vector<X, TaggingAllocator<X>>, + explicit TaggedValueType(Tag) { } + // CopyInsertable into vector<X, TaggingAllocator<X>>, + TaggedValueType(Tag, const TaggedValueType&) { } + // MoveInsertable into vector<X, TaggingAllocator<X>>, and + TaggedValueType(Tag, TaggedValueType&&) { } + + // not DefaultConstructible, CopyConstructible or MoveConstructible. + TaggedValueType() = delete; + TaggedValueType(const TaggedValueType&) = delete; + TaggedValueType(TaggedValueType&&) = delete; + + // CopyAssignable. + TaggedValueType& operator=(const TaggedValueType&) { return *this; } + + // MoveAssignable. + TaggedValueType& operator=(TaggedValueType&&) { return *this; } + +private: + // Not Destructible. + ~TaggedValueType() { } + + // Erasable from vector<X, TaggingAllocator<X>>. + template <class T> + friend class TaggingAllocator; +}; + +#endif /* TAGGING_ALLOCATOR_HPP */ Index: test/std/containers/sequences/vector/tagging_allocator_instantiation.pass.cpp =================================================================== --- /dev/null +++ test/std/containers/sequences/vector/tagging_allocator_instantiation.pass.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <vector> + +#include <vector> +#include "tagging_allocator.hpp" + +using VT = TaggedValueType<int, int, int>; +using Alloc = TaggingAllocator<VT>; + +template class std::vector<VT, Alloc>; + +int main() { + std::vector<VT, Alloc> v; + v.reserve(3); + v.emplace_back(); + v.emplace(v.begin()); + v.emplace(v.begin(), 1, 2, 3); +} \ No newline at end of file Index: test/libcxx/utilities/memory/allocator.traits/__is_alloc_constructible.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/utilities/memory/allocator.traits/__is_alloc_constructible.pass.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <memory> + +// template <class Alloc, class T, class ...Args> +// struct __is_alloc_constructible; + +#include <memory> +#include "tagging_allocator.hpp" + +template <class ...Args> +struct ConstructibleFrom { + explicit ConstructibleFrom(Args...) {} +}; + +void test_std_allocator() { + { + using A = std::allocator<char*>; // value_type different than constructed type + + static_assert(std::__is_alloc_constructible<A&, int>::value, ""); + + static_assert(std::__is_alloc_constructible<A&, int, int>::value, ""); + + static_assert(std::__is_alloc_constructible<A&, int, int const&>::value, ""); + static_assert(std::__is_alloc_constructible<A&, int, int&&>::value, ""); + static_assert(!std::__is_alloc_constructible<A&, int, char*>::value, + "bad argument"); + static_assert(!std::__is_alloc_constructible<A&, int, int, int>::value, + "too many arguments"); + A a; + int x = 101; + const int cx = -1; + int dummy; + a.construct(&dummy); + assert(dummy == 0); + a.construct(&dummy, 42); + assert(dummy == 42); + a.construct(&dummy, x); + assert(dummy == x); + a.construct(&dummy, cx); + assert(dummy == cx); + } + { + using A = std::allocator<int>; + static_assert(std::__is_alloc_constructible<A&, int>::value, ""); + static_assert(std::__is_alloc_constructible<A&, int, int>::value, ""); + static_assert(std::__is_alloc_constructible<A&, int, int const&>::value, ""); + static_assert(std::__is_alloc_constructible<A&, int, int&&>::value, ""); + static_assert(!std::__is_alloc_constructible<A&, int, char*>::value, + "bad argument"); + static_assert(!std::__is_alloc_constructible<A&, int, int, int>::value, + "too many arguments"); + A a; + int x = 101; + const int cx = -1; + int dummy; + a.construct(&dummy); + assert(dummy == 0); + a.construct(&dummy, 42); + assert(dummy == 42); + a.construct(&dummy, x); + assert(dummy == x); + a.construct(&dummy, cx); + assert(dummy == cx); + } + { + using A = std::allocator<const int>; + static_assert(std::__is_alloc_constructible<A&, int>::value, ""); + static_assert(std::__is_alloc_constructible<A&, int, int>::value, ""); + static_assert(std::__is_alloc_constructible<A&, int, int const&>::value, ""); + static_assert(std::__is_alloc_constructible<A&, int, int&&>::value, ""); + static_assert(!std::__is_alloc_constructible<A&, int, char*>::value, + "bad argument"); + static_assert(!std::__is_alloc_constructible<A&, int, int, int>::value, + "too many arguments"); + A a; + int x = 101; + const int cx = -1; + int dummy; + a.construct(&dummy); + assert(dummy == 0); + a.construct(&dummy, 42); + assert(dummy == 42); + a.construct(&dummy, x); + assert(dummy == x); + a.construct(&dummy, cx); + assert(dummy == cx); + } +} + +void test_allocator_traits_tagged_alloc() { + using VT = TaggedValueType<int>; + using A = TaggingAllocator<VT>; + A a; + VT* ptr = (VT*)std::malloc(sizeof(VT)); + a.construct(ptr); + a.destroy(ptr); + static_assert(std::__has_allocator_construct<A, VT*>::value, ""); + static_assert(std::__is_alloc_constructible<A, VT>::value, ""); + static_assert(std::__is_alloc_destructible<A, VT>::value, ""); + static_assert(!std::is_constructible<VT, Tag>::value, + "is_constructible<T> requires is_destructible<T>, which is not true"); +} + +int main() +{ + test_std_allocator(); + test_allocator_traits_tagged_alloc(); +} Index: include/vector =================================================================== --- include/vector +++ include/vector @@ -576,7 +576,8 @@ < __is_input_iterator <_InputIterator>::value && !__is_forward_iterator<_InputIterator>::value && - is_constructible< + __is_alloc_constructible< + allocator_type, value_type, typename iterator_traits<_InputIterator>::reference>::value, void @@ -586,7 +587,8 @@ typename enable_if < __is_forward_iterator<_ForwardIterator>::value && - is_constructible< + __is_alloc_constructible< + allocator_type, value_type, typename iterator_traits<_ForwardIterator>::reference>::value, void @@ -707,7 +709,8 @@ < __is_input_iterator <_InputIterator>::value && !__is_forward_iterator<_InputIterator>::value && - is_constructible< + __is_alloc_constructible< + allocator_type, value_type, typename iterator_traits<_InputIterator>::reference>::value, iterator @@ -717,7 +720,8 @@ typename enable_if < __is_forward_iterator<_ForwardIterator>::value && - is_constructible< + __is_alloc_constructible< + allocator_type, value_type, typename iterator_traits<_ForwardIterator>::reference>::value, iterator @@ -1364,7 +1368,8 @@ < __is_input_iterator <_InputIterator>::value && !__is_forward_iterator<_InputIterator>::value && - is_constructible< + __is_alloc_constructible< + _Allocator, _Tp, typename iterator_traits<_InputIterator>::reference>::value, void @@ -1381,7 +1386,8 @@ typename enable_if < __is_forward_iterator<_ForwardIterator>::value && - is_constructible< + __is_alloc_constructible< + _Allocator, _Tp, typename iterator_traits<_ForwardIterator>::reference>::value, void @@ -1881,8 +1887,8 @@ < __is_input_iterator <_InputIterator>::value && !__is_forward_iterator<_InputIterator>::value && - is_constructible< - _Tp, + __is_alloc_constructible< + _Allocator, _Tp, typename iterator_traits<_InputIterator>::reference>::value, typename vector<_Tp, _Allocator>::iterator >::type @@ -1938,8 +1944,8 @@ typename enable_if < __is_forward_iterator<_ForwardIterator>::value && - is_constructible< - _Tp, + __is_alloc_constructible< + _Allocator, _Tp, typename iterator_traits<_ForwardIterator>::reference>::value, typename vector<_Tp, _Allocator>::iterator >::type Index: include/type_traits =================================================================== --- include/type_traits +++ include/type_traits @@ -410,6 +410,9 @@ template <class _If, class _Then> struct _LIBCPP_TYPE_VIS_ONLY conditional<false, _If, _Then> {typedef _Then type;}; +template <class _Pred, class _If, class _Then> +struct _LIBCPP_TYPE_VIS_ONLY __lazy_conditional : conditional<_Pred::value, _If, _Then> {}; + #if _LIBCPP_STD_VER > 11 template <bool _Bp, class _If, class _Then> using conditional_t = typename conditional<_Bp, _If, _Then>::type; #endif Index: include/memory =================================================================== --- include/memory +++ include/memory @@ -1318,49 +1318,134 @@ #endif // _LIBCPP_HAS_NO_ADVANCED_SFINAE -#if !defined(_LIBCPP_HAS_NO_ADVANCED_SFINAE) && !defined(_LIBCPP_HAS_NO_VARIADICS) +#if !defined(_LIBCPP_CXX03_LANG) + +namespace __alloc_helpers { + + +template <class _Alloc, class _Pointer> +auto __has_allocator_destroy_test(_Alloc& __a, _Pointer&& __p) + -> decltype(__a.destroy(__p), true_type()); + +false_type __has_allocator_destroy_test(...); + +template <class _Alloc, class _Tp> +struct __has_allocator_destroy : decltype(__alloc_helpers::__has_allocator_destroy_test( + _VSTD::declval<_Alloc&>(), + _VSTD::declval<_Tp*>())) +{ +}; + +template <class _Alloc, class _Tp> +using __alloc_destroy_tag = typename + conditional< + __has_allocator_destroy<_Alloc, _Tp>::value, + integral_constant<int, 1>, + __lazy_conditional< + is_destructible<_Tp>, + integral_constant<int, 2>, + integral_constant<int, 0> + > + >::type::type; + + +template <class _Alloc, class _Tp> +inline _LIBCPP_INLINE_VISIBILITY +void __alloc_destroy_imp(integral_constant<int, 1>, _Alloc& __a, _Tp* __p) { + __a.destroy(__p); +} + +template <class _Alloc, class _Tp> +inline _LIBCPP_INLINE_VISIBILITY +void __alloc_destroy_imp(integral_constant<int, 2>, _Alloc&, _Tp* __p) { + __p->~_Tp(); +} + +template <class _Alloc, class _Tp> +inline _LIBCPP_INLINE_VISIBILITY +void __alloc_destroy(_Alloc& __a, _Tp* __p) { + __alloc_helpers::__alloc_destroy_imp(__alloc_destroy_tag<_Alloc, _Tp>(), __a, __p); +} template <class _Alloc, class _Tp, class ..._Args> -decltype(_VSTD::declval<_Alloc>().construct(_VSTD::declval<_Tp*>(), - _VSTD::declval<_Args>()...), - true_type()) -__has_construct_test(_Alloc&& __a, _Tp* __p, _Args&& ...__args); +auto __has_allocator_construct_test(_Alloc& __a, _Tp* __p, _Args&& ...__args) + -> decltype(__a.construct(__p, _VSTD::forward<_Args>(__args)...) + , true_type()); -template <class _Alloc, class _Pointer, class ..._Args> -false_type -__has_construct_test(const _Alloc& __a, _Pointer&& __p, _Args&& ...__args); +false_type __has_allocator_construct_test(...); template <class _Alloc, class _Pointer, class ..._Args> -struct __has_construct - : integral_constant<bool, - is_same< - decltype(__has_construct_test(declval<_Alloc>(), - declval<_Pointer>(), - declval<_Args>()...)), - true_type>::value> +struct __has_allocator_construct : decltype(__alloc_helpers::__has_allocator_construct_test( + _VSTD::declval<_Alloc&>(), + _VSTD::declval<_Pointer>(), + _VSTD::declval<_Args>()...)) { }; -template <class _Alloc, class _Pointer> -auto -__has_destroy_test(_Alloc&& __a, _Pointer&& __p) - -> decltype(__a.destroy(__p), true_type()); +template <class _Tp, class ..._Args> +auto __has_placement_new_test(_Tp* __p, _Args&& ...__args) + -> decltype(::new((void*)__p) _Tp(_VSTD::forward<_Args>(__args)...) + , true_type()); -template <class _Alloc, class _Pointer> -auto -__has_destroy_test(const _Alloc& __a, _Pointer&& __p) - -> false_type; +false_type __has_placement_new_test(...); -template <class _Alloc, class _Pointer> -struct __has_destroy - : integral_constant<bool, - is_same< - decltype(__has_destroy_test(declval<_Alloc>(), - declval<_Pointer>())), - true_type>::value> +template <class _Tp, class ..._Args> +struct __has_placement_new : decltype(__alloc_helpers::__has_placement_new_test( + (_Tp*)nullptr, + _VSTD::declval<_Args>()...)) { }; + +template <class _Alloc, class _Tp, class ..._Args> +using __alloc_construct_tag = typename + conditional< + __has_allocator_construct<_Alloc, _Tp*, _Args...>::value, + integral_constant<int, 1>, + __lazy_conditional< + __has_placement_new<_Tp, _Args...>, + integral_constant<int, 2>, + integral_constant<int, 0> + > + >::type::type; + + +template <class _Alloc, class _Tp, class... _Args> +inline _LIBCPP_INLINE_VISIBILITY +void __alloc_construct_imp(integral_constant<int, 1>, _Alloc& __a, _Tp* __p, _Args&&... __args) { + __a.construct(__p, _VSTD::forward<_Args>(__args)...); +} + +template <class _Alloc, class _Tp, class... _Args> +inline _LIBCPP_INLINE_VISIBILITY +void __alloc_construct_imp(integral_constant<int, 2>, _Alloc&, _Tp* __p, _Args&&... __args) { + ::new ((void*)__p) _Tp(_VSTD::forward<_Args>(__args)...); +} + +template <class _Alloc, class _Tp, class ..._Args> +inline _LIBCPP_INLINE_VISIBILITY +void __alloc_construct(_Alloc& __a, _Tp* __p, _Args&&... __args) { + __alloc_helpers::__alloc_construct_imp( + __alloc_construct_tag<_Alloc, _Tp, _Args...>(), + __a, __p, _VSTD::forward<_Args>(__args)...); +} + + +} // end namespace __alloc_helpers + +using __alloc_helpers::__has_allocator_construct; + +template <class _Alloc, class _Tp> +using __is_alloc_destructible = integral_constant<bool, + __alloc_helpers::__alloc_destroy_tag<_Alloc, _Tp>::value != 0 +>; + +template <class _Alloc, class _Tp, class ..._Args> +using __is_alloc_constructible = integral_constant<bool, + __alloc_helpers::__alloc_construct_tag<_Alloc, _Tp, _Args...>::value != 0 && + __alloc_helpers::__alloc_destroy_tag<_Alloc, _Tp>::value != 0 +>; + template <class _Alloc> auto __has_max_size_test(_Alloc&& __a) @@ -1399,28 +1484,17 @@ { }; -#else // _LIBCPP_HAS_NO_ADVANCED_SFINAE - -#ifndef _LIBCPP_HAS_NO_VARIADICS - -template <class _Alloc, class _Pointer, class ..._Args> -struct __has_construct - : false_type -{ -}; - -#else // _LIBCPP_HAS_NO_VARIADICS +#else // _LIBCPP_CXX03_LANG -template <class _Alloc, class _Pointer, class _Args> -struct __has_construct - : false_type -{ -}; +template <class _Alloc, class _Pointer, class _Tp> +struct __has_allocator_construct : false_type {}; -#endif // _LIBCPP_HAS_NO_VARIADICS +template <class _Alloc, class _Pointer, + class _T1 = void, class _T2 = void, class _T3 = void> +struct __is_alloc_constructible : true_type {}; template <class _Alloc, class _Pointer> -struct __has_destroy +struct __has_allocator_destroy : false_type { }; @@ -1437,7 +1511,7 @@ { }; -#endif // _LIBCPP_HAS_NO_ADVANCED_SFINAE +#endif // _LIBCPP_CXX03_LANG template <class _Alloc, class _Ptr, bool = __has_difference_type<_Alloc>::value> struct __alloc_traits_difference_type @@ -1497,12 +1571,14 @@ static void deallocate(allocator_type& __a, pointer __p, size_type __n) _NOEXCEPT {__a.deallocate(__p, __n);} -#ifndef _LIBCPP_HAS_NO_VARIADICS +#ifndef _LIBCPP_CXX03_LANG template <class _Tp, class... _Args> - _LIBCPP_INLINE_VISIBILITY - static void construct(allocator_type& __a, _Tp* __p, _Args&&... __args) - {__construct(__has_construct<allocator_type, _Tp*, _Args...>(), - __a, __p, _VSTD::forward<_Args>(__args)...);} + _LIBCPP_INLINE_VISIBILITY + static + typename enable_if<__is_alloc_constructible<allocator_type&, _Tp, _Args...>::value>::type + construct(allocator_type& __a, _Tp* __p, _Args&&... __args) { + __alloc_helpers::__alloc_construct(__a, __p, _VSTD::forward<_Args>(__args)...); + } #else // _LIBCPP_HAS_NO_VARIADICS template <class _Tp> _LIBCPP_INLINE_VISIBILITY @@ -1530,12 +1606,20 @@ { ::new ((void*)__p) _Tp(__a0, __a1, __a2); } -#endif // _LIBCPP_HAS_NO_VARIADICS +#endif // _LIBCPP_CXX03_LANG +#ifndef _LIBCPP_CXX03_LANG template <class _Tp> - _LIBCPP_INLINE_VISIBILITY - static void destroy(allocator_type& __a, _Tp* __p) - {__destroy(__has_destroy<allocator_type, _Tp*>(), __a, __p);} + _LIBCPP_INLINE_VISIBILITY static + typename enable_if<__is_alloc_destructible<allocator_type, _Tp>::value>::type + destroy(allocator_type& __a, _Tp* __p) + { __alloc_helpers::__alloc_destroy(__a, __p); } +#else + template <class _Tp> + _LIBCPP_INLINE_VISIBILITY static + static void destroy(allocator_type&, _Tp* __p) + { __p->~_Tp(); } +#endif _LIBCPP_INLINE_VISIBILITY static size_type max_size(const allocator_type& __a) _NOEXCEPT @@ -1564,7 +1648,7 @@ typename enable_if < (is_same<allocator_type, allocator<_Tp> >::value - || !__has_construct<allocator_type, _Tp*, _Tp>::value) && + || !__has_allocator_construct<allocator_type, _Tp*, _Tp>::value) && is_trivially_move_constructible<_Tp>::value, void >::type @@ -1594,7 +1678,7 @@ typename enable_if < (is_same<allocator_type, allocator<_Tp> >::value - || !__has_construct<allocator_type, _Tp*, _Tp>::value) && + || !__has_allocator_construct<allocator_type, _Tp*, _Tp>::value) && is_trivially_move_constructible<_Tp>::value, void >::type @@ -1628,7 +1712,7 @@ typename enable_if < (is_same<allocator_type, allocator<_Tp> >::value - || !__has_construct<allocator_type, _Tp*, _Tp>::value) && + || !__has_allocator_construct<allocator_type, _Tp*, _Tp>::value) && is_trivially_move_constructible<_Tp>::value, void >::type @@ -1651,18 +1735,6 @@ const_void_pointer, false_type) {return __a.allocate(__n);} -#ifndef _LIBCPP_HAS_NO_VARIADICS - template <class _Tp, class... _Args> - _LIBCPP_INLINE_VISIBILITY - static void __construct(true_type, allocator_type& __a, _Tp* __p, _Args&&... __args) - {__a.construct(__p, _VSTD::forward<_Args>(__args)...);} - template <class _Tp, class... _Args> - _LIBCPP_INLINE_VISIBILITY - static void __construct(false_type, allocator_type&, _Tp* __p, _Args&&... __args) - { - ::new ((void*)__p) _Tp(_VSTD::forward<_Args>(__args)...); - } -#endif // _LIBCPP_HAS_NO_VARIADICS template <class _Tp> _LIBCPP_INLINE_VISIBILITY @@ -1740,12 +1812,11 @@ {return size_type(~0) / sizeof(_Tp);} #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) template <class _Up, class... _Args> - _LIBCPP_INLINE_VISIBILITY - void - construct(_Up* __p, _Args&&... __args) - { + _LIBCPP_INLINE_VISIBILITY + typename enable_if<is_constructible<_Up, _Args...>::value>::type + construct(_Up* __p, _Args&&... __args) { ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...); - } + } #else // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) _LIBCPP_INLINE_VISIBILITY void @@ -1836,12 +1907,11 @@ {return size_type(~0) / sizeof(_Tp);} #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) template <class _Up, class... _Args> - _LIBCPP_INLINE_VISIBILITY - void - construct(_Up* __p, _Args&&... __args) - { + _LIBCPP_INLINE_VISIBILITY + typename enable_if<is_constructible<_Up, _Args...>::value>::type + construct(_Up* __p, _Args&&... __args) { ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...); - } + } #else // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) _LIBCPP_INLINE_VISIBILITY void
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits