diff options
author | Ville Voutilainen <ville.voutilainen@gmail.com> | 2016-09-21 20:25:16 +0300 |
---|---|---|
committer | Ville Voutilainen <ville@gcc.gnu.org> | 2016-09-21 20:25:16 +0300 |
commit | 557867852474743abd1e6b2ca678af8a8cf18b51 (patch) | |
tree | b4550db8a90a68c2afeea53d7398291da5409cc6 | |
parent | f524d5b34aaac95cb4b2ce7126002cd4fa9d5bae (diff) | |
download | gcc-557867852474743abd1e6b2ca678af8a8cf18b51.zip gcc-557867852474743abd1e6b2ca678af8a8cf18b51.tar.gz gcc-557867852474743abd1e6b2ca678af8a8cf18b51.tar.bz2 |
Implement LWG 2729 for tuple.
* include/std/tuple (_Tuple_impl(_Tuple_impl&&)):
Suppress conditionally.
(_Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&&)): Likewise.
(__is_tuple_impl_trait_impl, __is_tuple_impl_trait): New.
(_Tuple_impl(const _Head&)): Constrain.
(_Tuple_impl(_UHead&&)): Likewise.
(_Tuple_impl(_Tuple_impl&&)): Suppress conditionally.
(_Tuple_impl(const _Tuple_impl<_Idx, _UHead>&)): Constrain.
(_Tuple_impl(_Tuple_impl<_Idx, _UHead>&&)): Likewise.
(operator=(const tuple&)): Enable conditionally.
(operator=(tuple&&)): Suppress conditionally.
(operator=(const tuple<_UElements...>&)): Constrain.
(operator=(tuple<_UElements...>&&)): Likewise.
(operator=(const tuple&)): Enable conditionally (2-param tuple).
(operator=(tuple&&)): Suppress conditionally (2-param tuple).
(operator=(const tuple<_U1, _U2>&)): Constrain.
(operator=(tuple<_U1, _U2>&&)): Likewise.
(operator=(const pair<_U1, _U2>&)): Likewise.
(operator=(pair<_U1, _U2>&&)): Likewise.
* testsuite/20_util/tuple/element_access/get_neg.cc: Adjust.
* testsuite/20_util/tuple/tuple_traits.cc: New.
From-SVN: r240323
-rw-r--r-- | libstdc++-v3/ChangeLog | 25 | ||||
-rw-r--r-- | libstdc++-v3/include/std/tuple | 96 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc | 2 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/tuple/tuple_traits.cc | 244 |
4 files changed, 349 insertions, 18 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 0c35cd7..35dc2b5 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,30 @@ 2016-09-21 Ville Voutilainen <ville.voutilainen@gmail.com> + Implement LWG 2729 for tuple. + * include/std/tuple (_Tuple_impl(_Tuple_impl&&)): + Suppress conditionally. + (_Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&&)): Likewise. + (__is_tuple_impl_trait_impl, __is_tuple_impl_trait): New. + (_Tuple_impl(const _Head&)): Constrain. + (_Tuple_impl(_UHead&&)): Likewise. + (_Tuple_impl(_Tuple_impl&&)): Suppress conditionally. + (_Tuple_impl(const _Tuple_impl<_Idx, _UHead>&)): Constrain. + (_Tuple_impl(_Tuple_impl<_Idx, _UHead>&&)): Likewise. + (operator=(const tuple&)): Enable conditionally. + (operator=(tuple&&)): Suppress conditionally. + (operator=(const tuple<_UElements...>&)): Constrain. + (operator=(tuple<_UElements...>&&)): Likewise. + (operator=(const tuple&)): Enable conditionally (2-param tuple). + (operator=(tuple&&)): Suppress conditionally (2-param tuple). + (operator=(const tuple<_U1, _U2>&)): Constrain. + (operator=(tuple<_U1, _U2>&&)): Likewise. + (operator=(const pair<_U1, _U2>&)): Likewise. + (operator=(pair<_U1, _U2>&&)): Likewise. + * testsuite/20_util/tuple/element_access/get_neg.cc: Adjust. + * testsuite/20_util/tuple/tuple_traits.cc: New. + +2016-09-21 Ville Voutilainen <ville.voutilainen@gmail.com> + PR libstdc++/77537 Implement LWG 2729 for pair. * include/bits/stl_pair.h (_PCC): New. diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index c06a040..32b932f 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -220,8 +220,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr _Tuple_impl(const _Tuple_impl&) = default; constexpr - _Tuple_impl(_Tuple_impl&& __in) - noexcept(__and_<is_nothrow_move_constructible<_Head>, + _Tuple_impl(typename conditional< + __and_<is_move_constructible<_Head>, + is_move_constructible<_Inherited>>::value, + _Tuple_impl&&, __nonesuch&&>::type __in) + noexcept(__and_<is_nothrow_move_constructible<_Head>, is_nothrow_move_constructible<_Inherited>>::value) : _Inherited(std::move(_M_tail(__in))), _Base(std::forward<_Head>(_M_head(__in))) { } @@ -232,7 +235,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { } template<typename _UHead, typename... _UTails> - constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + constexpr _Tuple_impl(typename conditional< + __and_<is_move_constructible<_Head>, + is_move_constructible<_Inherited>>::value, + _Tuple_impl<_Idx, _UHead, _UTails...>&&, + __nonesuch&&>::type __in) : _Inherited(std::move (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), _Base(std::forward<_UHead> @@ -338,6 +345,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } }; + template<typename...> + struct __is_tuple_impl_trait_impl : false_type + { }; + + template<std::size_t _Idx, typename... _Tp> + struct __is_tuple_impl_trait_impl<_Tuple_impl<_Idx, _Tp...>> : true_type + { }; + + template<typename _Tp> + struct __is_tuple_impl_trait : public __is_tuple_impl_trait_impl<_Tp> + { }; + // Basis case of inheritance recursion. template<std::size_t _Idx, typename _Head> struct _Tuple_impl<_Idx, _Head> @@ -356,11 +375,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr _Tuple_impl() : _Base() { } + template<typename _Dummy=void, + typename enable_if<is_constructible<_Base, const _Head&>::value, + bool>::type=true> explicit constexpr _Tuple_impl(const _Head& __head) : _Base(__head) { } - template<typename _UHead> + template<typename _UHead, + typename enable_if<__and_<is_constructible<_Base, _UHead&&>, + __not_<__is_tuple_impl_trait< + typename + remove_reference<_UHead>::type>> + >::value, + bool>::type = true> explicit constexpr _Tuple_impl(_UHead&& __head) : _Base(std::forward<_UHead>(__head)) { } @@ -368,15 +396,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr _Tuple_impl(const _Tuple_impl&) = default; constexpr - _Tuple_impl(_Tuple_impl&& __in) + _Tuple_impl(typename conditional< + is_move_constructible<_Head>::value, + _Tuple_impl&&, __nonesuch&&>::type __in) noexcept(is_nothrow_move_constructible<_Head>::value) : _Base(std::forward<_Head>(_M_head(__in))) { } - template<typename _UHead> + template<typename _UHead, + typename enable_if<!is_same<_Head, _UHead>::value, + bool>::type = true> constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in) : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in)) { } - template<typename _UHead> + template<typename _UHead, + typename enable_if<!is_same<_Head, _UHead>::value, + bool>::type = true> constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in) : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) { } @@ -832,14 +866,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { } tuple& - operator=(const tuple& __in) + operator=(typename + conditional<__and_<is_copy_assignable<_Elements>...>::value, + const tuple&, const __nonesuch&>::type __in) { static_cast<_Inherited&>(*this) = __in; return *this; } tuple& - operator=(tuple&& __in) + operator=(typename + conditional<__and_<is_move_assignable<_Elements>...>::value, + tuple&&, __nonesuch&&>::type __in) noexcept(is_nothrow_move_assignable<_Inherited>::value) { static_cast<_Inherited&>(*this) = std::move(__in); @@ -848,7 +886,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename... _UElements, typename = typename enable_if<sizeof...(_UElements) - == sizeof...(_Elements)>::type> + == sizeof...(_Elements) + && + __and_<is_assignable<_Elements&, + const _UElements&>...>::value>::type> tuple& operator=(const tuple<_UElements...>& __in) { @@ -858,7 +899,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename... _UElements, typename = typename enable_if<sizeof...(_UElements) - == sizeof...(_Elements)>::type> + == sizeof...(_Elements) + && + __and_<is_assignable<_Elements&, + _UElements&&>...>::value>::type> tuple& operator=(tuple<_UElements...>&& __in) { @@ -1189,14 +1233,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::forward<_U2>(__in.second)) { } tuple& - operator=(const tuple& __in) + operator=(typename + conditional<__and_<is_copy_assignable<_T1>, + is_copy_assignable<_T2>>::value, + const tuple&, const __nonesuch&>::type __in) { static_cast<_Inherited&>(*this) = __in; return *this; } tuple& - operator=(tuple&& __in) + operator=(typename + conditional<__and_<is_move_assignable<_T1>, + is_move_assignable<_T2>>::value, + tuple&&, __nonesuch&&>::type __in) noexcept(is_nothrow_move_assignable<_Inherited>::value) { static_cast<_Inherited&>(*this) = std::move(__in); @@ -1204,7 +1254,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _U1, typename _U2> - tuple& + typename + enable_if<__and_<is_assignable<_T1&, const _U1&>, + is_assignable<_T2&, const _U2&>>::value, + tuple&>::type operator=(const tuple<_U1, _U2>& __in) { static_cast<_Inherited&>(*this) = __in; @@ -1212,7 +1265,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _U1, typename _U2> - tuple& + typename + enable_if<__and_<is_assignable<_T1&, _U1&&>, + is_assignable<_T2&, _U2&&>>::value, + tuple&>::type operator=(tuple<_U1, _U2>&& __in) { static_cast<_Inherited&>(*this) = std::move(__in); @@ -1220,7 +1276,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _U1, typename _U2> - tuple& + typename + enable_if<__and_<is_assignable<_T1&, const _U1&>, + is_assignable<_T2&, const _U2&>>::value, + tuple&>::type operator=(const pair<_U1, _U2>& __in) { this->_M_head(*this) = __in.first; @@ -1229,7 +1288,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _U1, typename _U2> - tuple& + typename + enable_if<__and_<is_assignable<_T1&, _U1&&>, + is_assignable<_T2&, _U2&&>>::value, + tuple&>::type operator=(pair<_U1, _U2>&& __in) { this->_M_head(*this) = std::forward<_U1>(__in.first); diff --git a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc index 5bcf576..1c08d45 100644 --- a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc +++ b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc @@ -17,7 +17,7 @@ // { dg-options "-fno-show-column" } // { dg-do compile { target c++14 } } -// { dg-error "in range" "" { target *-*-* } 1280 } +// { dg-error "in range" "" { target *-*-* } 1342 } #include <tuple> diff --git a/libstdc++-v3/testsuite/20_util/tuple/tuple_traits.cc b/libstdc++-v3/testsuite/20_util/tuple/tuple_traits.cc new file mode 100644 index 0000000..b72f535 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/tuple_traits.cc @@ -0,0 +1,244 @@ +// { dg-do compile { target c++11 } } + +// Copyright (C) 2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <tuple> +#include <type_traits> +#include <utility> +#include <vector> +#include <memory> + +using namespace std; + +struct Poison +{ + Poison(Poison&&) = delete; +}; + + +int main() +{ + static_assert(!is_copy_constructible<Poison>::value, ""); + static_assert(!is_move_constructible<Poison>::value, ""); + static_assert(!is_copy_assignable<Poison>::value, ""); + static_assert(!is_move_assignable<Poison>::value, ""); + + static_assert(!is_copy_constructible<std::tuple<Poison>>::value, ""); + static_assert(!is_move_constructible<std::tuple<Poison>>::value, ""); + static_assert(!is_copy_assignable<std::tuple<Poison>>::value, ""); + static_assert(!is_move_assignable<std::tuple<Poison>>::value, ""); + + static_assert(!is_copy_constructible<std::tuple<int, Poison>>::value, + ""); + static_assert(!is_move_constructible<std::tuple<int, Poison>>::value, + ""); + static_assert(!is_copy_assignable<std::tuple<int, Poison>>::value, ""); + static_assert(!is_move_assignable<std::tuple<int, Poison>>::value, ""); + static_assert(!is_constructible<std::tuple<int, Poison>&, + std::tuple<char, Poison>&>::value, ""); + static_assert(!is_assignable<std::tuple<int, Poison>&, + std::tuple<char, Poison>&>::value, ""); + static_assert(!is_constructible<std::tuple<int, Poison>&, + std::tuple<char, Poison>>::value, ""); + static_assert(!is_assignable<std::tuple<int, Poison>&, + std::tuple<char, Poison>>::value, ""); + static_assert(!is_constructible<std::tuple<int, Poison>&, + std::pair<char, Poison>&>::value, ""); + static_assert(!is_assignable<std::tuple<int, Poison>&, + std::pair<char, Poison>&>::value, ""); + static_assert(!is_constructible<std::tuple<int, Poison>&, + std::pair<char, Poison>>::value, ""); + static_assert(!is_assignable<std::tuple<int, Poison>&, + std::pair<char, Poison>>::value, ""); + + static_assert(!is_copy_constructible< + std::tuple<int, int, Poison>>::value, ""); + static_assert(!is_move_constructible< + std::tuple<int, int, Poison>>::value, ""); + static_assert(!is_copy_assignable< + std::tuple<int, int, Poison>>::value, ""); + static_assert(!is_move_assignable< + std::tuple<int, int, Poison>>::value, ""); + static_assert(!is_constructible< + std::tuple<int, int,Poison>&, + std::tuple<int, char, Poison>&>::value, ""); + static_assert(!is_assignable< + std::tuple<int, int, Poison>&, + std::tuple<int, char, Poison>&>::value, ""); + static_assert(!is_constructible< + std::tuple<int, int, Poison>&, + std::tuple<int, char, Poison>>::value, ""); + static_assert(!is_assignable< + std::tuple<int, int, Poison>&, + std::tuple<int, char, Poison>>::value, ""); + static_assert(!is_constructible< + std::tuple<int, int, Poison>&, + std::pair<char, Poison>&>::value, ""); + static_assert(!is_assignable< + std::tuple<int, int, Poison>&, + std::pair<char, Poison>&>::value, ""); + static_assert(!is_constructible< + std::tuple<int, int, Poison>&, + std::pair<char, Poison>>::value, ""); + static_assert(!is_assignable< + std::tuple<int, int, Poison>&, + std::pair<char, Poison>>::value, ""); + + static_assert(is_trivially_copy_constructible<tuple<int>>::value, ""); + static_assert(!is_trivially_move_constructible<tuple<int>>::value, ""); + + static_assert(!is_trivially_copy_assignable<tuple<int>>::value, ""); + static_assert(!is_trivially_move_assignable<tuple<int>>::value, ""); + + static_assert(is_copy_constructible<tuple<int>>::value, ""); + static_assert(is_move_constructible<tuple<int>>::value, ""); + + static_assert(is_copy_assignable<tuple<int>>::value, ""); + static_assert(is_move_assignable<tuple<int>>::value, ""); + + static_assert(!is_trivially_copy_constructible< + tuple<vector<int>>>::value, ""); + static_assert(!is_trivially_move_constructible< + tuple<vector<int>>>::value, ""); + + static_assert(!is_trivially_copy_assignable< + tuple<vector<int>>>::value, ""); + static_assert(!is_trivially_move_assignable< + tuple<vector<int>>>::value, ""); + + static_assert(is_copy_constructible<tuple<vector<int>>>::value, ""); + static_assert(is_move_constructible<tuple<vector<int>>>::value, ""); + + static_assert(is_copy_assignable<tuple<vector<int>>>::value, ""); + static_assert(is_move_assignable<tuple<vector<int>>>::value, ""); + + static_assert(!is_trivially_copy_constructible< + tuple<unique_ptr<int>>>::value, ""); + static_assert(!is_trivially_move_constructible< + tuple<unique_ptr<int>>>::value, ""); + + static_assert(!is_trivially_copy_assignable< + tuple<unique_ptr<int>>>::value, ""); + static_assert(!is_trivially_move_assignable< + tuple<unique_ptr<int>>>::value, ""); + static_assert(!is_copy_constructible< + tuple<unique_ptr<int>>>::value, ""); + static_assert(is_move_constructible<tuple<unique_ptr<int>>>::value, ""); + + static_assert(!is_copy_assignable<tuple<unique_ptr<int>>>::value, ""); + static_assert(is_move_assignable<tuple<unique_ptr<int>>>::value, ""); + + static_assert(is_trivially_copy_constructible< + tuple<int, int>>::value, ""); + static_assert(!is_trivially_move_constructible< + tuple<int, int>>::value, ""); + + static_assert(!is_trivially_copy_assignable< + tuple<int, int>>::value, ""); + static_assert(!is_trivially_move_assignable< + tuple<int, int>>::value, ""); + + static_assert(is_copy_constructible<tuple<int, int>>::value, ""); + static_assert(is_move_constructible<tuple<int, int>>::value, ""); + + static_assert(is_copy_assignable<tuple<int, int>>::value, ""); + static_assert(is_move_assignable<tuple<int, int>>::value, ""); + static_assert(!is_trivially_copy_constructible< + tuple<int, vector<int>>>::value, ""); + static_assert(!is_trivially_move_constructible< + tuple<int, vector<int>>>::value, ""); + + static_assert(!is_trivially_copy_assignable< + tuple<int, vector<int>>>::value, ""); + static_assert(!is_trivially_move_assignable< + tuple<int, vector<int>>>::value, ""); + + static_assert(is_copy_constructible< + tuple<int, vector<int>>>::value, ""); + static_assert(is_move_constructible< + tuple<int, vector<int>>>::value, ""); + + static_assert(is_copy_assignable<tuple<int, vector<int>>>::value, ""); + static_assert(is_move_assignable<tuple<int, vector<int>>>::value, ""); + + static_assert(!is_trivially_copy_constructible< + tuple<int, unique_ptr<int>>>::value, ""); + static_assert(!is_trivially_move_constructible< + tuple<int, unique_ptr<int>>>::value, ""); + + static_assert(!is_trivially_copy_assignable< + tuple<int, unique_ptr<int>>>::value, ""); + static_assert(!is_trivially_move_assignable< + tuple<int, unique_ptr<int>>>::value, ""); + + static_assert(!is_copy_constructible< + tuple<int, unique_ptr<int>>>::value, ""); + static_assert(is_move_constructible< + tuple<int, unique_ptr<int>>>::value, ""); + + static_assert(!is_copy_assignable< + tuple<int, unique_ptr<int>>>::value, ""); + static_assert(is_move_assignable< + tuple<int, unique_ptr<int>>>::value, ""); + + static_assert(is_copy_constructible<tuple<int, int, int>>::value, ""); + static_assert(is_move_constructible<tuple<int, int, int>>::value, ""); + + static_assert(is_copy_assignable<tuple<int, int, int>>::value, ""); + static_assert(is_move_assignable<tuple<int, int, int>>::value, ""); + + static_assert(!is_trivially_copy_constructible< + tuple<int, int, vector<int>>>::value, ""); + static_assert(!is_trivially_move_constructible< + tuple<int, int, vector<int>>>::value, ""); + + static_assert(!is_trivially_copy_assignable< + tuple<int, int, vector<int>>>::value, ""); + static_assert(!is_trivially_move_assignable< + tuple<int, int, vector<int>>>::value, ""); + + static_assert(is_copy_constructible< + tuple<int, int, vector<int>>>::value, ""); + static_assert(is_move_constructible< + tuple<int, int, vector<int>>>::value, ""); + + static_assert(is_copy_assignable< + tuple<int, int, vector<int>>>::value, ""); + static_assert(is_move_assignable< + tuple<int, int, vector<int>>>::value, ""); + + static_assert(!is_trivially_copy_constructible< + tuple<int, int, unique_ptr<int>>>::value, ""); + static_assert(!is_trivially_move_constructible< + tuple<int, int, unique_ptr<int>>>::value, ""); + + static_assert(!is_trivially_copy_assignable< + tuple<int, int, unique_ptr<int>>>::value, ""); + static_assert(!is_trivially_move_assignable< + tuple<int, int, unique_ptr<int>>>::value, ""); + + static_assert(!is_copy_constructible< + tuple<int, int, unique_ptr<int>>>::value, ""); + static_assert(is_move_constructible< + tuple<int, int, unique_ptr<int>>>::value, ""); + + static_assert(!is_copy_assignable< + tuple<int, int, unique_ptr<int>>>::value, ""); + static_assert(is_move_assignable< + tuple<int, int, unique_ptr<int>>>::value, ""); +} |