Implement LWG 2485
authorVille Voutilainen <ville.voutilainen@gmail.com>
Mon, 30 Oct 2017 14:31:04 +0000 (16:31 +0200)
committerVille Voutilainen <ville@gcc.gnu.org>
Mon, 30 Oct 2017 14:31:04 +0000 (16:31 +0200)
* include/debug/array (get(const array<_Tp, _Nm>&&)): New.
* include/std/array (get(const array<_Tp, _Nm>&&)): Likewise.
* include/std/tuple (get(const tuple<_Elements...>&&)): Likewise.
(get(const tuple<_Types...>&&)): Likewise.
* include/std/utility
(__pair_get::__const_move_get(const std::pair<_Tp1, _Tp2>&&)):
Likewise.
(get(const std::pair<_Tp1, _Tp2>&&)): Likewise.
(get(const pair<_Tp, _Up>&&)): Likewise.
(get(const pair<_Up, _Tp>&&)): Likewise.
* testsuite/20_util/pair/astuple/get.cc: Add tests for
new overloads.
* testsuite/20_util/pair/astuple/get_by_type.cc: Likewise.
* testsuite/20_util/tuple/element_access/get2.cc: Likewise.
* testsuite/20_util/tuple/element_access/get2_by_type.cc: Likewise.
* testsuite/23_containers/array/tuple_interface/get.cc: Likewise.
* testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc:
Adjust.
* testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc:
Likewise.

From-SVN: r254222

12 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/include/debug/array
libstdc++-v3/include/std/array
libstdc++-v3/include/std/tuple
libstdc++-v3/include/std/utility
libstdc++-v3/testsuite/20_util/pair/astuple/get.cc
libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type.cc
libstdc++-v3/testsuite/20_util/tuple/element_access/get2.cc
libstdc++-v3/testsuite/20_util/tuple/element_access/get2_by_type.cc
libstdc++-v3/testsuite/23_containers/array/tuple_interface/get.cc
libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc
libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc

index 796e32c1ba35900f764c0cef817585b543999447..994eca814c71e2aff5a7f6268e92d3ae2b88f343 100644 (file)
@@ -1,3 +1,27 @@
+2017-10-30  Ville Voutilainen  <ville.voutilainen@gmail.com>
+
+       Implement LWG 2485
+       * include/debug/array (get(const array<_Tp, _Nm>&&)): New.
+       * include/std/array (get(const array<_Tp, _Nm>&&)): Likewise.
+       * include/std/tuple (get(const tuple<_Elements...>&&)): Likewise.
+       (get(const tuple<_Types...>&&)): Likewise.
+       * include/std/utility
+       (__pair_get::__const_move_get(const std::pair<_Tp1, _Tp2>&&)):
+       Likewise.
+       (get(const std::pair<_Tp1, _Tp2>&&)): Likewise.
+       (get(const pair<_Tp, _Up>&&)): Likewise.
+       (get(const pair<_Up, _Tp>&&)): Likewise.
+       * testsuite/20_util/pair/astuple/get.cc: Add tests for
+       new overloads.
+       * testsuite/20_util/pair/astuple/get_by_type.cc: Likewise.
+       * testsuite/20_util/tuple/element_access/get2.cc: Likewise.
+       * testsuite/20_util/tuple/element_access/get2_by_type.cc: Likewise.
+       * testsuite/23_containers/array/tuple_interface/get.cc: Likewise.
+       * testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc:
+       Adjust.
+       * testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc:
+       Likewise.
+
 2017-10-27  Jonathan Wakely  <jwakely@redhat.com>
 
        * include/bits/node_handle.h (_Node_insert_return::get): Avoid
index 9c279221040a64f8e779708934921a98ead1861c..95edc84f38b9e449c742d4348a62fbb3369b0868 100644 (file)
@@ -306,6 +306,14 @@ namespace __debug
       return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
        _S_ref(__arr._M_elems, _Int);
     }
+
+  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
+    constexpr const _Tp&&
+    get(const array<_Tp, _Nm>&& __arr) noexcept
+    {
+      static_assert(_Int < _Nm, "index is out of bounds");
+      return std::move(__debug::get<_Int>(__arr));
+    }
 } // namespace __debug
 
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
index f058c0621454d6dd5b3ee123e7c98af5f8978b60..01f7100bae0b99c98eae19f30845ff9d7409a029 100644 (file)
@@ -328,6 +328,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        _S_ref(__arr._M_elems, _Int);
     }
 
+  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
+    constexpr const _Tp&&
+    get(const array<_Tp, _Nm>&& __arr) noexcept
+    {
+      static_assert(_Int < _Nm, "array index is within bounds");
+      return std::move(_GLIBCXX_STD_C::get<_Int>(__arr));
+    }
+
 _GLIBCXX_END_NAMESPACE_CONTAINER
 } // namespace std
 
index 1f5365ad02681ca7babc6b68dcea2cbfa63bcb47..ac03c9ec402801d79c7597065f045505a47068e9 100644 (file)
@@ -1329,6 +1329,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return std::forward<__element_type&&>(std::get<__i>(__t));
     }
 
+  /// Return a const rvalue reference to the ith element of a const tuple rvalue.
+  template<std::size_t __i, typename... _Elements>
+    constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
+    get(const tuple<_Elements...>&& __t) noexcept
+    {
+      typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
+      return std::forward<const __element_type&&>(std::get<__i>(__t));
+    }
+
 #if __cplusplus > 201103L
 
 #define __cpp_lib_tuples_by_type 201304
@@ -1360,6 +1369,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     constexpr const _Tp&
     get(const tuple<_Types...>& __t) noexcept
     { return std::__get_helper2<_Tp>(__t); }
+
+  /// Return a const reference to the unique element of type _Tp of
+  /// a const tuple rvalue.
+  template <typename _Tp, typename... _Types>
+    constexpr const _Tp&&
+    get(const tuple<_Types...>&& __t) noexcept
+    { return std::forward<const _Tp&&>(std::__get_helper2<_Tp>(__t)); }
 #endif
 
   // This class performs the comparison operations on tuples
index 29a626004f9fd2dc932b28c7561e1d8e8144ae73..e7386320e2a15bce6bbaf635fe1c27e8116bf342 100644 (file)
@@ -184,6 +184,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         static constexpr const _Tp1&
         __const_get(const std::pair<_Tp1, _Tp2>& __pair) noexcept
         { return __pair.first; }
+
+      template<typename _Tp1, typename _Tp2>
+        static constexpr const _Tp1&&
+        __const_move_get(const std::pair<_Tp1, _Tp2>&& __pair) noexcept
+        { return std::forward<const _Tp1>(__pair.first); }
     };
 
   template<>
@@ -203,6 +208,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         static constexpr const _Tp2&
         __const_get(const std::pair<_Tp1, _Tp2>& __pair) noexcept
         { return __pair.second; }
+
+      template<typename _Tp1, typename _Tp2>
+        static constexpr const _Tp2&&
+        __const_move_get(const std::pair<_Tp1, _Tp2>&& __pair) noexcept
+        { return std::forward<const _Tp2>(__pair.second); }
     };
 
   template<std::size_t _Int, class _Tp1, class _Tp2>
@@ -220,6 +230,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     get(const std::pair<_Tp1, _Tp2>& __in) noexcept
     { return __pair_get<_Int>::__const_get(__in); }
 
+  template<std::size_t _Int, class _Tp1, class _Tp2>
+    constexpr const typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type&&
+    get(const std::pair<_Tp1, _Tp2>&& __in) noexcept
+    { return __pair_get<_Int>::__const_move_get(std::move(__in)); }
+
 #if __cplusplus > 201103L
 
 #define __cpp_lib_tuples_by_type 201304
@@ -239,6 +254,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     get(pair<_Tp, _Up>&& __p) noexcept
     { return std::move(__p.first); }
 
+  template <typename _Tp, typename _Up>
+    constexpr const _Tp&&
+    get(const pair<_Tp, _Up>&& __p) noexcept
+    { return std::move(__p.first); }
+
   template <typename _Tp, typename _Up>
     constexpr _Tp&
     get(pair<_Up, _Tp>& __p) noexcept
@@ -254,6 +274,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     get(pair<_Up, _Tp>&& __p) noexcept
     { return std::move(__p.second); }
 
+  template <typename _Tp, typename _Up>
+    constexpr const _Tp&&
+    get(const pair<_Up, _Tp>&& __p) noexcept
+    { return std::move(__p.second); }
+
 #define __cpp_lib_exchange_function 201304
 
   /// Assign @p __new_val to @p __obj and return its previous value.
index 80939741f6c58b75f3ea226ab11b690d5c1afbb7..e81af3b2f33f06d73fe6655216a5d1fc8d476c10 100644 (file)
@@ -27,4 +27,9 @@ void test01()
 
   float&& pfirst __attribute__((unused)) = std::get<0>(std::move(p));
   int&&  psecond __attribute__((unused)) = std::get<1>(std::move(p));
+
+  const std::pair<float, int> cp;
+
+  const float&& cpfirst __attribute__((unused)) = std::get<0>(std::move(cp));
+  const int&&  cpsecond __attribute__((unused)) = std::get<1>(std::move(cp));
 }
index 8d8bf0efe94bac4668632c1bf2dd1de3d2eec067..1e70fbcf43f35e84993622775599a309a738c9d7 100644 (file)
@@ -25,4 +25,11 @@ void test01()
 
   float&& pfirst __attribute__((unused)) = std::get<float>(std::move(p));
   int&&  psecond __attribute__((unused)) = std::get<int>(std::move(p));
+
+  const std::pair<float, int> cp;
+
+  const float&& cpfirst __attribute__((unused)) =
+    std::get<float>(std::move(cp));
+  const int&&  cpsecond __attribute__((unused)) =
+    std::get<int>(std::move(cp));
 }
index 14bdb0c6b1f37a4c4f38a3330ecc572671ab6ad5..bc0f1bc899b19f7206b12fa1a2704738c54618a5 100644 (file)
@@ -37,4 +37,19 @@ void test01()
   short&&  t3one __attribute__((unused)) = std::get<0>(std::move(t3));
   int&&    t3two __attribute__((unused)) = std::get<1>(std::move(t3));
   double&& t3thr __attribute__((unused)) = std::get<2>(std::move(t3));
+
+  const std::tuple<int> ct1;
+
+  const int&&   ct1one __attribute__((unused)) = std::get<0>(std::move(ct1));
+
+  const std::tuple<float, int> ct2;
+
+  const float&& ct2one __attribute__((unused)) = std::get<0>(std::move(ct2));
+  const int&&   ct2two __attribute__((unused)) = std::get<1>(std::move(ct2));
+
+  const std::tuple<short, int, double> ct3;
+
+  const short&&  ct3one __attribute__((unused)) = std::get<0>(std::move(ct3));
+  const int&&    ct3two __attribute__((unused)) = std::get<1>(std::move(ct3));
+  const double&& ct3thr __attribute__((unused)) = std::get<2>(std::move(ct3));
 }
index 337934d57e2cec9676de0c12efc67672c43bc31e..cdc1030059a24593d9c26332c2c9d1ac224a60aa 100644 (file)
@@ -35,4 +35,22 @@ void test01()
   short&&  t3one __attribute__((unused)) = std::get<short>(std::move(t3));
   int&&    t3two __attribute__((unused)) = std::get<int>(std::move(t3));
   double&& t3thr __attribute__((unused)) = std::get<double>(std::move(t3));
+
+  const std::tuple<int> ct1;
+
+  const int&&   ct1one __attribute__((unused)) = std::get<int>(std::move(ct1));
+
+  const std::tuple<float, int> ct2;
+
+  const float&& ct2one __attribute__((unused)) = std::get<0>(std::move(ct2));
+  const int&&   ct2two __attribute__((unused)) = std::get<int>(std::move(ct2));
+
+  const std::tuple<short, int, double> ct3;
+
+  const short&&  ct3one __attribute__((unused)) =
+    std::get<short>(std::move(ct3));
+  const int&&    ct3two __attribute__((unused)) =
+    std::get<int>(std::move(ct3));
+  const double&& ct3thr __attribute__((unused)) =
+    std::get<double>(std::move(ct3));
 }
index a8c403c6cc790d391d3b814b6c9cc6dba5e67c5a..8bc0afb0e9c4946445de3f1648071ae2bbc87552 100644 (file)
@@ -27,4 +27,9 @@ void test01()
 
   int&& aone __attribute__((unused)) = std::get<0>(std::move(a));
   int&& atwo __attribute__((unused)) = std::get<1>(std::move(a));
+
+  const std::array<int, 2> ca{};
+
+  const int&& caone __attribute__((unused)) = std::get<0>(std::move(ca));
+  const int&& catwo __attribute__((unused)) = std::get<1>(std::move(ca));
 }
index e433c6e0a63d50f56be1efa4c4f615a8b6f4804f..8e8ef0d756e63abd32ef2f631041fc173126ee13 100644 (file)
@@ -22,4 +22,4 @@
 
 typedef std::tuple_element<1, std::array<int, 1>>::type type;
 
-// { dg-error "static assertion failed" "" { target *-*-* } 323 }
+// { dg-error "static assertion failed" "" { target *-*-* } 331 }
index 493449a235ba6fd078d91d7f58c8ceb6a7f072b0..4e8eb3291cbd0919a8bc6ac83f8744efdddd623f 100644 (file)
@@ -22,4 +22,4 @@
 
 typedef std::tuple_element<1, std::array<int, 1>>::type type;
 
-// { dg-error "static assertion failed" "" { target *-*-* } 357 }
+// { dg-error "static assertion failed" "" { target *-*-* } 365 }