vsapsai updated this revision to Diff 154326.
vsapsai added a comment.

- Use a better way to detect presence of `construct` with required signature. 
Clean up tests.

Don't know how other compilers will handle this but Clang accepts this
C++11-looking-but-accepted-in-C++03 code.


https://reviews.llvm.org/D48753

Files:
  libcxx/include/memory
  
libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter.pass.cpp
  
libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp
  libcxx/test/support/min_allocator.h

Index: libcxx/test/support/min_allocator.h
===================================================================
--- libcxx/test/support/min_allocator.h
+++ libcxx/test/support/min_allocator.h
@@ -14,6 +14,7 @@
 #include <cstdlib>
 #include <cstddef>
 #include <cassert>
+#include <climits>
 
 #include "test_macros.h"
 
@@ -131,6 +132,57 @@
     friend bool operator!=(malloc_allocator x, malloc_allocator y) {return !(x == y);}
 };
 
+template <class T>
+struct cpp03_allocator : bare_allocator<T>
+{
+    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 <class T> bool cpp03_allocator<T>::construct_called = false;
+
+template <class T>
+struct cpp03_overload_allocator : bare_allocator<T>
+{
+    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<T>());
+    }
+    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 <class T> bool cpp03_overload_allocator<T>::construct_called = false;
+
 
 #if TEST_STD_VER >= 11
 
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<int, cpp03_allocator<int> > 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<int, cpp03_overload_allocator<int> > 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/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<int, cpp03_allocator<int> > 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<int, cpp03_overload_allocator<int> > 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/include/memory
===================================================================
--- libcxx/include/memory
+++ libcxx/include/memory
@@ -1459,23 +1459,18 @@
 
 #else  // _LIBCPP_CXX03_LANG
 
-#ifndef _LIBCPP_HAS_NO_VARIADICS
-
-template <class _Alloc, class _Pointer, class ..._Args>
-struct __has_construct
-    : false_type
-{
-};
-
-#else  // _LIBCPP_HAS_NO_VARIADICS
+template <class _Alloc, class _Pointer, class _Args, class = void>
+struct __has_construct : std::false_type {};
 
 template <class _Alloc, class _Pointer, class _Args>
-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 <class _Alloc, class _Pointer>
 struct __has_destroy
@@ -1570,9 +1565,10 @@
             }
     template <class _Tp, class _A0>
         _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<allocator_type, _Tp*, const _A0&>(),
+                            __a, __p, __a0);
             }
     template <class _Tp, class _A0, class _A1>
         _LIBCPP_INLINE_VISIBILITY
@@ -1720,6 +1716,19 @@
             {
                 ::new ((void*)__p) _Tp(_VSTD::forward<_Args>(__args)...);
             }
+#else  // _LIBCPP_HAS_NO_VARIADICS
+    template <class _Tp, class _A0>
+        _LIBCPP_INLINE_VISIBILITY
+        static void __construct(true_type, allocator_type& __a, _Tp* __p,
+                                const _A0& __a0)
+            {__a.construct(__p, __a0);}
+    template <class _Tp, class _A0>
+        _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 <class _Tp>
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to