diff mbox

Simplify std::tuple helpers and fix C++14 bug.

Message ID 20140613120117.GF30729@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely June 13, 2014, 12:01 p.m. UTC
On 15/05/14 11:38 +0100, Jonathan Wakely wrote:
>On 15/05/14 07:36 +0200, Daniel Krügler wrote:
>>Looking at the definition of the new alias
>>
>>__cv_tuple_size
>>
>>you might want to apply LWG 2313
>>
>>http://cplusplus.github.io/LWG/lwg-defects.html#2313
>>
>>and simplify its definition even further.
>
>I forgot about that. With that resolution the __cv_tuple_size alias
>doesn't seem worth using, it's simple enough anyway. Thanks!
>
>Tested x86_64-linux, committed to trunk.

Here's a simpler patch for the 4.9 branch, just fixing the bug and
implementing the DR, committed.
diff mbox

Patch

commit b6ae8cc2cd135241ae2a3bd539f9c87b7ad6fe87
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Jun 13 12:33:32 2014 +0100

    	* include/std/tuple (tuple_size<cv _Tp>): Implement LWG 2313.
    	(get<_Tp>(tuple<_Types...>&&)): Use forward instead of move.
    	* testsuite/20_util/tuple/element_access/get_by_type.cc: Test rvalues.

diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 03d87d7..103c99e 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -719,23 +719,19 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct tuple_size;
 
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2313. tuple_size should always derive from integral_constant<size_t, N>
   template<typename _Tp>
     struct tuple_size<const _Tp>
-    : public integral_constant<
-             typename remove_cv<decltype(tuple_size<_Tp>::value)>::type,
-             tuple_size<_Tp>::value> { };
+    : public integral_constant<size_t, tuple_size<_Tp>::value> { };
 
   template<typename _Tp>
     struct tuple_size<volatile _Tp>
-    : public integral_constant<
-             typename remove_cv<decltype(tuple_size<_Tp>::value)>::type,
-             tuple_size<_Tp>::value> { };
+    : public integral_constant<size_t, tuple_size<_Tp>::value> { };
 
   template<typename _Tp>
     struct tuple_size<const volatile _Tp>
-    : public integral_constant<
-             typename remove_cv<decltype(tuple_size<_Tp>::value)>::type,
-             tuple_size<_Tp>::value> { };
+    : public integral_constant<size_t, tuple_size<_Tp>::value> { };
 
   /// class tuple_size
   template<typename... _Elements>
@@ -752,9 +748,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
     { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
 
-  // Return a reference (const reference, rvalue reference) to the ith element
-  // of a tuple.  Any const or non-const ref elements are returned with their
-  // original type.
+  /// Return a reference to the ith element of a tuple.
   template<std::size_t __i, typename... _Elements>
     constexpr typename __add_ref<
                       typename tuple_element<__i, tuple<_Elements...>>::type
@@ -762,6 +756,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     get(tuple<_Elements...>& __t) noexcept
     { return std::__get_helper<__i>(__t); }
 
+  /// Return a const reference to the ith element of a const tuple.
   template<std::size_t __i, typename... _Elements>
     constexpr typename __add_c_ref<
                       typename tuple_element<__i, tuple<_Elements...>>::type
@@ -769,6 +764,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     get(const tuple<_Elements...>& __t) noexcept
     { return std::__get_helper<__i>(__t); }
 
+  /// Return an rvalue reference to the ith element of a tuple rvalue.
   template<std::size_t __i, typename... _Elements>
     constexpr typename __add_r_ref<
                       typename tuple_element<__i, tuple<_Elements...>>::type
@@ -788,22 +784,26 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     __get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
     { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
 
+  /// Return a reference to the unique element of type _Tp of a tuple.
   template <typename _Tp, typename... _Types>
     constexpr _Tp&
     get(tuple<_Types...>& __t) noexcept
     { return std::__get_helper2<_Tp>(__t); }
 
+  /// Return a reference to the unique element of type _Tp of a tuple rvalue.
   template <typename _Tp, typename... _Types>
     constexpr _Tp&&
     get(tuple<_Types...>&& __t) noexcept
-    { return std::move(std::__get_helper2<_Tp>(__t)); }
+    { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); }
 
+  /// Return a const reference to the unique element of type _Tp of a tuple.
   template <typename _Tp, typename... _Types>
     constexpr const _Tp&
     get(const tuple<_Types...>& __t) noexcept
     { return std::__get_helper2<_Tp>(__t); }
 #endif
 
+
   // This class helps construct the various comparison operations on tuples
   template<std::size_t __check_equal_size, std::size_t __i, std::size_t __j,
 	   typename _Tp, typename _Up>
diff --git a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_by_type.cc b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_by_type.cc
index 226e9e4..042f214 100644
--- a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_by_type.cc
+++ b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_by_type.cc
@@ -41,4 +41,8 @@  main()
   get<1>(b)=5;
   VERIFY(get<int>(b)==1 && get<int&>(b)==5 && get<const int&>(b)==2);
   VERIFY(j==5);
+  // test rvalue overload:
+  VERIFY(get<int>(std::move(b))==1);
+  VERIFY(get<int&>(std::move(b))==5);
+  VERIFY(get<const int&>(std::move(b))==2);
 }