EricWF updated this revision to Diff 63635.
EricWF added a comment.
- Don't use `is_constructible` in the `__is_alloc_constructible`
implementation. `is_constructible<T, ...>` requires `is_destructible<T>`, but
that isn't required within allocators. Instead this trait checks the validity
of the placement new expression.
- Add tests for `__is_alloc_constructible`. Not complete but a good start.
- Implement sample changes to `<vector>` that fix PR28412
(https://llvm.org/bugs/show_bug.cgi?id=28412). See
`tagging_allocator_instantation.pass.cpp` for the example test.
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/libcxx/utilities/memory/allocator.traits/vector_instant.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/libcxx/utilities/memory/allocator.traits/vector_instant.pass.cpp
===================================================================
--- /dev/null
+++ test/libcxx/utilities/memory/allocator.traits/vector_instant.pass.cpp
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+
+#include <vector>
+#include "tagging_allocator.hpp"
+
+using VT = TaggedValueType<int>;
+using Alloc = TaggingAllocator<VT>;
+
+template class std::vector<VT, Alloc>;
+
+int main() {
+
+}
\ 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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits