LWG 2975 ensure construct(pair<T,U>*, ...) used to construct pairs
authorJonathan Wakely <jwakely@redhat.com>
Mon, 18 Jun 2018 20:17:44 +0000 (21:17 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Mon, 18 Jun 2018 20:17:44 +0000 (21:17 +0100)
* include/std/scoped_allocator (__not_pair): Define SFINAE helper.
(construct(_Tp*, _Args&&...)): Remove from overload set when _Tp is
a specialization of std::pair.
* testsuite/20_util/scoped_allocator/construct_pair.cc: Ensure
pair elements are constructed correctly.

From-SVN: r261716

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/scoped_allocator
libstdc++-v3/testsuite/20_util/scoped_allocator/construct_pair.cc

index 0b81f047a178cb8d25a78557bc011300938fc247..89bcf2f5d5c0a4765f5f9830979301c561751daa 100644 (file)
@@ -1,5 +1,12 @@
 2018-06-18  Jonathan Wakely  <jwakely@redhat.com>
 
+       LWG 2975 ensure construct(pair<T,U>*, ...) used to construct pairs
+       * include/std/scoped_allocator (__not_pair): Define SFINAE helper.
+       (construct(_Tp*, _Args&&...)): Remove from overload set when _Tp is
+       a specialization of std::pair.
+       * testsuite/20_util/scoped_allocator/construct_pair.cc: Ensure
+       pair elements are constructed correctly.
+
        LWG 2989 hide path iostream operators from normal lookup
        * include/bits/fs_path.h (operator<<, operator>>): Define inline as
        friends.
index 195db397ac99b44f739522d7859d542afe551862..ea62f11351702962fdffd389d2e6172b5e3843e6 100644 (file)
@@ -241,6 +241,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
             is_constructible<_OuterAlloc, _Alloc>::value
           >::type;
 
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 2975. Missing case for pair construction in scoped [...] allocators
+      template<typename _Tp>
+       struct __not_pair { using type = void; };
+
+      template<typename _Tp, typename _Up>
+       struct __not_pair<pair<_Tp, _Up>> { };
+
     public:
       typedef _OuterAlloc                       outer_allocator_type;
       typedef typename __inner_type::__type     inner_allocator_type;
@@ -348,13 +356,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { return __traits::max_size(outer_allocator()); }
 
       template<typename _Tp, typename... _Args>
-        void construct(_Tp* __p, _Args&&... __args)
-        {
-          auto& __inner = inner_allocator();
-          auto __use_tag
-            = __use_alloc<_Tp, inner_allocator_type, _Args...>(__inner);
-          _M_construct(__use_tag, __p, std::forward<_Args>(__args)...);
-        }
+       typename __not_pair<_Tp>::type
+       construct(_Tp* __p, _Args&&... __args)
+       {
+         auto& __inner = inner_allocator();
+         auto __use_tag
+           = __use_alloc<_Tp, inner_allocator_type, _Args...>(__inner);
+         _M_construct(__use_tag, __p, std::forward<_Args>(__args)...);
+       }
 
       template<typename _T1, typename _T2, typename... _Args1,
               typename... _Args2>
index 341328e487fd24a3cdc652d9ac45a24cd12a34a8..b34efc88798279388c6705e28c9ba58f350586f5 100644 (file)
@@ -73,9 +73,37 @@ test03()
   a.deallocate(ptr, 1);
 }
 
+void
+test04()
+{
+  struct X
+  {
+    using allocator_type = std::allocator<int>;
+    X() = default;
+    X(const X&) { throw 1; }
+    X(const X&, const allocator_type&) { }
+  };
+
+  struct Y
+  {
+    using allocator_type = std::allocator<int>;
+    Y() = default;
+    Y(const Y&) = delete;
+    Y(std::allocator_arg_t, const allocator_type&, const Y&) { }
+  };
+
+  using pair_type = std::pair<X, Y>;
+  std::scoped_allocator_adaptor<std::allocator<pair_type>> a;
+  auto ptr = a.allocate(1);
+  /* not const */ pair_type p;
+  a.construct(ptr, p); // LWG 2975
+  a.deallocate(ptr, 1);
+}
+
 int main()
 {
   test01();
   test02();
   test03();
+  test04();
 }