From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 35996 invoked by alias); 5 Jun 2015 14:44:54 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 35976 invoked by uid 89); 5 Jun 2015 14:44:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.0 required=5.0 tests=AWL,BAYES_50,KAM_LAZY_DOMAIN_SECURITY,SPF_HELO_PASS,T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 05 Jun 2015 14:44:51 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (Postfix) with ESMTPS id 24A413C1C1D; Fri, 5 Jun 2015 14:44:50 +0000 (UTC) Received: from localhost (ovpn-116-119.ams2.redhat.com [10.36.116.119]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t55EimT2018899; Fri, 5 Jun 2015 10:44:49 -0400 Date: Fri, 05 Jun 2015 14:58:00 -0000 From: Jonathan Wakely To: Ville Voutilainen Cc: "gcc-patches@gcc.gnu.org" , libstdc++@gcc.gnu.org Subject: Re: [libstdc++ PATCH] Implement __is_nothrow_swappable and use it Message-ID: <20150605144448.GN12728@redhat.com> References: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="61jdw2sOBCFtR2d/" Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.23 (2014-03-12) X-SW-Source: 2015-06/txt/msg00466.txt.bz2 --61jdw2sOBCFtR2d/ Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline Content-length: 1021 On 01/05/15 12:47 +0300, Ville Voutilainen wrote: >This patch partially solves the problem described in N4426, which is >basically LWG >issue 2456, which in turn is caused by CWG DR 1330. Some remarks: >- the __is_swappable and __is_nothrow_swappable are at this time not >meant to be general traits, they make the shortcut of automatically transforming >their template parameter into a reference, which the truly general trait >as described in N4426 wouldn't do. >- swap is now constrained.. >- ..which means that everything from bits/move.h moves to type_traits since >swap now needs type_traits. type_traits becomes ok to include in pre-c++14 >modes, but only enables the parts that work in pre-c++14 modes. >- this patch does _not_ yet implement N4426. I've committed this slightly altered patch, which doesn't move swap into but just declares it there. The definition remains in and including in c++98 mode is still an error. Tested powerpc64le-linux, committed to trunk. --61jdw2sOBCFtR2d/ Content-Type: text/x-patch; charset=us-ascii Content-Disposition: attachment; filename="patch.txt" Content-length: 15872 commit d485df2eebd2869b3a17a3d67b2a394dbbbedab9 Author: Jonathan Wakely Date: Fri Jun 5 13:20:53 2015 +0100 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. diff --git a/libstdc++-v3/include/bits/algorithmfwd.h b/libstdc++-v3/include/bits/algorithmfwd.h index 1dfc4ad..c972f33 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 1dfd667..88c4f7b 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 3daeb60..490b005 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 48e1ee7..5f8e6fb 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 3ff307f..0ed212e 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 7bb74c1..34e6281 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 5198bb3..434ca96 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 24be44f..40fbd46 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 ad132bd..ccea02b 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 b8ec61f..2eae61b 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 0000000..93fa94b --- /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 0000000..2372349 --- /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 0000000..bc778b5 --- /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), ""); +} --61jdw2sOBCFtR2d/--