From ddb63209a8dc059a7b2a137d7a1859222bb43dd6 Mon Sep 17 00:00:00 2001 From: Ville Voutilainen Date: Fri, 5 Jun 2015 17:44:26 +0300 Subject: [PATCH] Add __is_nothrow_swappable and take it into use. 2015-06-04 Ville Voutilainen Add __is_nothrow_swappable and take it into use. * include/bits/algorithmfwd.h (swap): Only declare for C++98 mode. * include/bits/move.h (swap): Add constraints in C++11 and later. * include/bits/stl_pair.h (swap): Use __is_nothrow_swappable for the free swap function for pair. * include/bits/stl_queue.h (swap): Use __is_nothrow_swappable for the free swap functions for queue and priority_queue. * include/bits/stl_stack.h (swap): Use __is_nothrow_swappable for the free swap function for stack. * include/debug/array (swap): Use __is_nothrow_swappable for the free swap function for array. * include/profile/array (swap): Likewise. * include/std/array (swap): Likewise. * include/std/tuple (_Tuple_impl::_M_swap): Use __is_nothrow_swappable. * include/std/type_traits (__is_swappable_impl::__is_swappable, __is_nothrow_swappable_impl, __is_nothrow_swappable): New. * testsuite/20_util/is_nothrow_swappable/requirements/ explicit_instantiation.cc: New. * testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc: New. * testsuite/20_util/is_nothrow_swappable/value.cc: New. From-SVN: r224153 --- libstdc++-v3/ChangeLog | 24 +++++++ libstdc++-v3/include/bits/algorithmfwd.h | 21 +++--- libstdc++-v3/include/bits/move.h | 17 +++-- libstdc++-v3/include/bits/stl_pair.h | 4 +- libstdc++-v3/include/bits/stl_queue.h | 5 +- libstdc++-v3/include/bits/stl_stack.h | 2 +- libstdc++-v3/include/debug/array | 2 +- libstdc++-v3/include/profile/array | 2 +- libstdc++-v3/include/std/array | 2 +- libstdc++-v3/include/std/tuple | 7 +- libstdc++-v3/include/std/type_traits | 46 ++++++++++++ .../requirements/explicit_instantiation.cc | 27 +++++++ .../requirements/typedefs.cc | 32 +++++++++ .../20_util/is_nothrow_swappable/value.cc | 72 +++++++++++++++++++ 14 files changed, 234 insertions(+), 29 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/explicit_instantiation.cc create mode 100644 libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc create mode 100644 libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 89e0fcfae7b..4efd866729d 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,27 @@ +2015-06-04 Ville Voutilainen + + Add __is_nothrow_swappable and take it into use. + * include/bits/algorithmfwd.h (swap): Only declare for C++98 mode. + * include/bits/move.h (swap): Add constraints in C++11 and later. + * include/bits/stl_pair.h (swap): Use __is_nothrow_swappable + for the free swap function for pair. + * include/bits/stl_queue.h (swap): Use __is_nothrow_swappable + for the free swap functions for queue and priority_queue. + * include/bits/stl_stack.h (swap): Use __is_nothrow_swappable + for the free swap function for stack. + * include/debug/array (swap): Use __is_nothrow_swappable + for the free swap function for array. + * include/profile/array (swap): Likewise. + * include/std/array (swap): Likewise. + * include/std/tuple (_Tuple_impl::_M_swap): Use __is_nothrow_swappable. + * include/std/type_traits (__is_swappable_impl::__is_swappable, + __is_nothrow_swappable_impl, __is_nothrow_swappable): New. + * testsuite/20_util/is_nothrow_swappable/requirements/ + explicit_instantiation.cc: New. + * testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc: + New. + * testsuite/20_util/is_nothrow_swappable/value.cc: New. + 2015-06-03 François Dumont fdumont@gcc.gnu.org> * testsuite/23_containers/list/61347.cc: Add dg-require-normal-mode. diff --git a/libstdc++-v3/include/bits/algorithmfwd.h b/libstdc++-v3/include/bits/algorithmfwd.h index 1dfc4ad7b15..c972f33c0f3 100644 --- a/libstdc++-v3/include/bits/algorithmfwd.h +++ b/libstdc++-v3/include/bits/algorithmfwd.h @@ -566,22 +566,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _BIter stable_partition(_BIter, _BIter, _Predicate); - template - void - swap(_Tp&, _Tp&) -#if __cplusplus >= 201103L - noexcept(__and_, - is_nothrow_move_assignable<_Tp>>::value) -#endif - ; +#if __cplusplus < 201103L + // For C++11 swap() is declared in . template - void - swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) -#if __cplusplus >= 201103L - noexcept(noexcept(swap(*__a, *__b))) + inline void + swap(_Tp& __a, _Tp& __b); + + template + inline void + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]); #endif - ; template _FIter2 diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h index 1dfd667a716..88c4f7b3e5c 100644 --- a/libstdc++-v3/include/bits/move.h +++ b/libstdc++-v3/include/bits/move.h @@ -172,11 +172,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @return Nothing. */ template - inline void - swap(_Tp& __a, _Tp& __b) + inline #if __cplusplus >= 201103L + typename enable_if<__and_, + is_move_assignable<_Tp>>::value>::type + swap(_Tp& __a, _Tp& __b) noexcept(__and_, is_nothrow_move_assignable<_Tp>>::value) +#else + void + swap(_Tp& __a, _Tp& __b) #endif { // concept requirements @@ -191,10 +196,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // DR 809. std::swap should be overloaded for array types. /// Swap the contents of two arrays. template - inline void - swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) + inline #if __cplusplus >= 201103L + typename enable_if<__is_swappable_impl::__is_swappable<_Tp>::value>::type + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) noexcept(noexcept(swap(*__a, *__b))) +#else + void + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) #endif { for (size_t __n = 0; __n < _Nm; ++__n) diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index 3daeb60ab5c..490b00565a0 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -192,8 +192,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void swap(pair& __p) - noexcept(noexcept(swap(first, __p.first)) - && noexcept(swap(second, __p.second))) + noexcept(__is_nothrow_swappable<_T1>::value + && __is_nothrow_swappable<_T2>::value) { using std::swap; swap(first, __p.first); diff --git a/libstdc++-v3/include/bits/stl_queue.h b/libstdc++-v3/include/bits/stl_queue.h index 48e1ee79c6d..5f8e6fb9ab1 100644 --- a/libstdc++-v3/include/bits/stl_queue.h +++ b/libstdc++-v3/include/bits/stl_queue.h @@ -247,7 +247,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L void swap(queue& __q) - noexcept(noexcept(swap(c, __q.c))) + noexcept(__is_nothrow_swappable<_Tp>::value) { using std::swap; swap(c, __q.c); @@ -541,7 +541,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L void swap(priority_queue& __pq) - noexcept(noexcept(swap(c, __pq.c)) && noexcept(swap(comp, __pq.comp))) + noexcept(__is_nothrow_swappable<_Tp>::value + && __is_nothrow_swappable<_Compare>::value) { using std::swap; swap(c, __pq.c); diff --git a/libstdc++-v3/include/bits/stl_stack.h b/libstdc++-v3/include/bits/stl_stack.h index 3ff307ff6ad..0ed212e4307 100644 --- a/libstdc++-v3/include/bits/stl_stack.h +++ b/libstdc++-v3/include/bits/stl_stack.h @@ -221,7 +221,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L void swap(stack& __s) - noexcept(noexcept(swap(c, __s.c))) + noexcept(__is_nothrow_swappable<_Tp>::value) { using std::swap; swap(c, __s.c); diff --git a/libstdc++-v3/include/debug/array b/libstdc++-v3/include/debug/array index 7bb74c17664..34e6281da5a 100644 --- a/libstdc++-v3/include/debug/array +++ b/libstdc++-v3/include/debug/array @@ -84,7 +84,7 @@ namespace __debug void swap(array& __other) - noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))) + noexcept(__is_nothrow_swappable<_Tp>::value) { std::swap_ranges(begin(), end(), __other.begin()); } // Iterators. diff --git a/libstdc++-v3/include/profile/array b/libstdc++-v3/include/profile/array index 5198bb3af9c..434ca968d84 100644 --- a/libstdc++-v3/include/profile/array +++ b/libstdc++-v3/include/profile/array @@ -63,7 +63,7 @@ namespace __profile void swap(array& __other) - noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))) + noexcept(__is_nothrow_swappable<_Tp>::value) { std::swap_ranges(begin(), end(), __other.begin()); } // Iterators. diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array index 24be44f5b13..40fbd46c559 100644 --- a/libstdc++-v3/include/std/array +++ b/libstdc++-v3/include/std/array @@ -113,7 +113,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void swap(array& __other) - noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))) + noexcept(__is_nothrow_swappable<_Tp>::value) { std::swap_ranges(begin(), end(), __other.begin()); } // Iterators. diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index ad132bd8308..ccea02b4ffd 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -324,9 +324,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION protected: void _M_swap(_Tuple_impl& __in) - noexcept(noexcept(swap(std::declval<_Head&>(), - std::declval<_Head&>())) - && noexcept(_M_tail(__in)._M_swap(_M_tail(__in)))) + noexcept(__is_nothrow_swappable<_Head>::value + && noexcept(_M_tail(__in)._M_swap(_M_tail(__in)))) { using std::swap; swap(_M_head(*this), _M_head(__in)); @@ -451,7 +450,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION protected: void _M_swap(_Tuple_impl& __in) - noexcept(noexcept(swap(std::declval<_Head&>(), std::declval<_Head&>()))) + noexcept(__is_nothrow_swappable<_Head>::value) { using std::swap; swap(_M_head(*this), _M_head(__in)); diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index b8ec61f6892..2eae61bb8f4 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -2427,6 +2427,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : true_type \ { }; + + namespace __is_swappable_impl { + template + struct __is_swappable : public false_type + { }; + } + + template + inline + typename enable_if<__and_, + is_move_assignable<_Tp>>::value>::type + swap(_Tp&, _Tp&) + noexcept(__and_, + is_nothrow_move_assignable<_Tp>>::value); + + template + inline + typename enable_if<__is_swappable_impl::__is_swappable<_Tp>::value>::type + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) + noexcept(noexcept(swap(*__a, *__b))); + + namespace __is_swappable_impl { + using std::swap; + + template + struct __is_swappable<_Tp, __void_t(), + declval<_Tp&>()))>> + : public true_type + { }; + } + + template + struct __is_nothrow_swappable_impl + : public __bool_constant(), declval<_Tp&>()))> + { }; + + template + struct __is_nothrow_swappable_impl : public false_type + { }; + + template + struct __is_nothrow_swappable + : public __is_nothrow_swappable_impl< + __is_swappable_impl::__is_swappable<_Tp>::value, _Tp> + { }; + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/explicit_instantiation.cc new file mode 100644 index 00000000000..93fa94b5ea0 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/explicit_instantiation.cc @@ -0,0 +1,27 @@ +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +// Copyright (C) 2015 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 +// . + +#include + +namespace std +{ + typedef short test_type; + template struct std::__is_nothrow_swappable; +} diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc new file mode 100644 index 00000000000..2372349b7dc --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/requirements/typedefs.cc @@ -0,0 +1,32 @@ +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +// Copyright (C) 2015 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 +// . + +#include + + +void test01() +{ + // Check for required typedefs + typedef std::__is_nothrow_swappable test_type; + typedef test_type::value_type value_type; + typedef test_type::type type; + typedef test_type::type::value_type type_value_type; + typedef test_type::type::type type_type; +} diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.cc new file mode 100644 index 00000000000..bc778b5bd7f --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_nothrow_swappable/value.cc @@ -0,0 +1,72 @@ +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +// Copyright (C) 2015 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 +// . + +#include +#include +#include +#include +#include +#include +#include + +namespace funny { + struct F {}; + void swap(F&, F&) = delete; +} +void test01() +{ + using std::__is_nothrow_swappable; + using std::__is_swappable_impl::__is_swappable; + using namespace __gnu_test; + // Positive tests. + static_assert(test_property<__is_swappable, int>(true), ""); + static_assert(test_property<__is_nothrow_swappable, int>(true), ""); + static_assert(test_property<__is_nothrow_swappable, int[1]>(true), ""); + static_assert(test_property<__is_nothrow_swappable, + std::pair>(true), ""); + static_assert(test_property<__is_nothrow_swappable, + std::tuple>(true), ""); + static_assert(test_property<__is_nothrow_swappable, + std::array>(true), ""); + static_assert(test_property<__is_nothrow_swappable, + std::queue>(true), ""); + static_assert(test_property<__is_nothrow_swappable, + std::priority_queue>(true), ""); + static_assert(test_property<__is_nothrow_swappable, + std::stack>(true), ""); + // Negative tests. + static_assert(test_property<__is_swappable, construct::DelCopy>(false), ""); + static_assert(test_property<__is_swappable, funny::F>(false), ""); + static_assert(test_property<__is_swappable, funny::F[1]>(false), ""); + static_assert(test_property<__is_nothrow_swappable, + ThrowCopyConsClass>(false), ""); + static_assert(test_property<__is_nothrow_swappable, + std::pair>(false), ""); + static_assert(test_property<__is_nothrow_swappable, + std::tuple>(false), ""); + static_assert(test_property<__is_nothrow_swappable, + std::array>(false), ""); + static_assert(test_property<__is_nothrow_swappable, + std::queue>(false), ""); + static_assert(test_property<__is_nothrow_swappable, + std::priority_queue>(false), ""); + static_assert(test_property<__is_nothrow_swappable, + std::stack>(false), ""); +} -- 2.30.2