From ccbbf8df05abc41ef86565706976c5ad403291e7 Mon Sep 17 00:00:00 2001 From: Ville Voutilainen Date: Mon, 30 Oct 2017 16:31:04 +0200 Subject: [PATCH] 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. From-SVN: r254222 --- libstdc++-v3/ChangeLog | 24 ++++++++++++++++++ libstdc++-v3/include/debug/array | 8 ++++++ libstdc++-v3/include/std/array | 8 ++++++ libstdc++-v3/include/std/tuple | 16 ++++++++++++ libstdc++-v3/include/std/utility | 25 +++++++++++++++++++ .../testsuite/20_util/pair/astuple/get.cc | 5 ++++ .../20_util/pair/astuple/get_by_type.cc | 7 ++++++ .../20_util/tuple/element_access/get2.cc | 15 +++++++++++ .../tuple/element_access/get2_by_type.cc | 18 +++++++++++++ .../array/tuple_interface/get.cc | 5 ++++ .../tuple_element_debug_neg.cc | 2 +- .../tuple_interface/tuple_element_neg.cc | 2 +- 12 files changed, 133 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 796e32c1ba3..994eca814c7 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,27 @@ +2017-10-30 Ville Voutilainen + + 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 * include/bits/node_handle.h (_Node_insert_return::get): Avoid diff --git a/libstdc++-v3/include/debug/array b/libstdc++-v3/include/debug/array index 9c279221040..95edc84f38b 100644 --- a/libstdc++-v3/include/debug/array +++ b/libstdc++-v3/include/debug/array @@ -306,6 +306,14 @@ namespace __debug return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: _S_ref(__arr._M_elems, _Int); } + + template + 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 diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array index f058c062145..01f7100bae0 100644 --- a/libstdc++-v3/include/std/array +++ b/libstdc++-v3/include/std/array @@ -328,6 +328,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _S_ref(__arr._M_elems, _Int); } + template + 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 diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 1f5365ad026..ac03c9ec402 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -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 + 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(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 + constexpr const _Tp&& + get(const tuple<_Types...>&& __t) noexcept + { return std::forward(std::__get_helper2<_Tp>(__t)); } #endif // This class performs the comparison operations on tuples diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility index 29a626004f9..e7386320e2a 100644 --- a/libstdc++-v3/include/std/utility +++ b/libstdc++-v3/include/std/utility @@ -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 + static constexpr const _Tp1&& + __const_move_get(const std::pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward(__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 + static constexpr const _Tp2&& + __const_move_get(const std::pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward(__pair.second); } }; template @@ -220,6 +230,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION get(const std::pair<_Tp1, _Tp2>& __in) noexcept { return __pair_get<_Int>::__const_get(__in); } + template + 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 + constexpr const _Tp&& + get(const pair<_Tp, _Up>&& __p) noexcept + { return std::move(__p.first); } + template 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 + 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. diff --git a/libstdc++-v3/testsuite/20_util/pair/astuple/get.cc b/libstdc++-v3/testsuite/20_util/pair/astuple/get.cc index 80939741f6c..e81af3b2f33 100644 --- a/libstdc++-v3/testsuite/20_util/pair/astuple/get.cc +++ b/libstdc++-v3/testsuite/20_util/pair/astuple/get.cc @@ -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 cp; + + const float&& cpfirst __attribute__((unused)) = std::get<0>(std::move(cp)); + const int&& cpsecond __attribute__((unused)) = std::get<1>(std::move(cp)); } diff --git a/libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type.cc b/libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type.cc index 8d8bf0efe94..1e70fbcf43f 100644 --- a/libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type.cc +++ b/libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type.cc @@ -25,4 +25,11 @@ void test01() float&& pfirst __attribute__((unused)) = std::get(std::move(p)); int&& psecond __attribute__((unused)) = std::get(std::move(p)); + + const std::pair cp; + + const float&& cpfirst __attribute__((unused)) = + std::get(std::move(cp)); + const int&& cpsecond __attribute__((unused)) = + std::get(std::move(cp)); } diff --git a/libstdc++-v3/testsuite/20_util/tuple/element_access/get2.cc b/libstdc++-v3/testsuite/20_util/tuple/element_access/get2.cc index 14bdb0c6b1f..bc0f1bc899b 100644 --- a/libstdc++-v3/testsuite/20_util/tuple/element_access/get2.cc +++ b/libstdc++-v3/testsuite/20_util/tuple/element_access/get2.cc @@ -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 ct1; + + const int&& ct1one __attribute__((unused)) = std::get<0>(std::move(ct1)); + + const std::tuple 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 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)); } diff --git a/libstdc++-v3/testsuite/20_util/tuple/element_access/get2_by_type.cc b/libstdc++-v3/testsuite/20_util/tuple/element_access/get2_by_type.cc index 337934d57e2..cdc1030059a 100644 --- a/libstdc++-v3/testsuite/20_util/tuple/element_access/get2_by_type.cc +++ b/libstdc++-v3/testsuite/20_util/tuple/element_access/get2_by_type.cc @@ -35,4 +35,22 @@ void test01() short&& t3one __attribute__((unused)) = std::get(std::move(t3)); int&& t3two __attribute__((unused)) = std::get(std::move(t3)); double&& t3thr __attribute__((unused)) = std::get(std::move(t3)); + + const std::tuple ct1; + + const int&& ct1one __attribute__((unused)) = std::get(std::move(ct1)); + + const std::tuple ct2; + + const float&& ct2one __attribute__((unused)) = std::get<0>(std::move(ct2)); + const int&& ct2two __attribute__((unused)) = std::get(std::move(ct2)); + + const std::tuple ct3; + + const short&& ct3one __attribute__((unused)) = + std::get(std::move(ct3)); + const int&& ct3two __attribute__((unused)) = + std::get(std::move(ct3)); + const double&& ct3thr __attribute__((unused)) = + std::get(std::move(ct3)); } diff --git a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get.cc b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get.cc index a8c403c6cc7..8bc0afb0e9c 100644 --- a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get.cc +++ b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get.cc @@ -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 ca{}; + + const int&& caone __attribute__((unused)) = std::get<0>(std::move(ca)); + const int&& catwo __attribute__((unused)) = std::get<1>(std::move(ca)); } diff --git a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc index e433c6e0a63..8e8ef0d756e 100644 --- a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc @@ -22,4 +22,4 @@ typedef std::tuple_element<1, std::array>::type type; -// { dg-error "static assertion failed" "" { target *-*-* } 323 } +// { dg-error "static assertion failed" "" { target *-*-* } 331 } diff --git a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc index 493449a235b..4e8eb3291cb 100644 --- a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc @@ -22,4 +22,4 @@ typedef std::tuple_element<1, std::array>::type type; -// { dg-error "static assertion failed" "" { target *-*-* } 357 } +// { dg-error "static assertion failed" "" { target *-*-* } 365 } -- 2.30.2