From patchwork Wed Apr 17 19:10:41 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Fran=C3=A7ois_Dumont?= X-Patchwork-Id: 237346 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id A5D1A2C017B for ; Thu, 18 Apr 2013 05:11:06 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:references :in-reply-to:content-type; q=dns; s=default; b=a+fSqLbX741m5Wl/J 8FlGxD6LAh9FtWDofOi0SLN4ZOcDH/6KkJ2m/daURuNTaZlunGKAHIszSbwQm0Hx 4Kxez0KF6UsVhSWIMCU7cPrRpzgvgi2yRbl2p8T+Uzn3NWuLy824DNKUJEpgF+75 oOgNxwXI+cnrqQzOlqxskqwAwQ= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:references :in-reply-to:content-type; s=default; bh=adI8z1HnJSyo2o5ZHUdSPOI FxcQ=; b=HtKoRSqNBIbjKg46FGWk5/Y6h/YG7gOIBf9oOoead8jJ4/C4lUH33YH POvxC4ECiSy4llkJez1VmoS2LsUZFMHKjgaTZLQh4APtwBkd3UU/+XJ2zrG8twao jLF2WLc9oAyKiJ9b/d5xxWzLoGbBGHXoC6U1AICUCuSxf/MuuwbA= Received: (qmail 24659 invoked by alias); 17 Apr 2013 19:10:49 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 24636 invoked by uid 89); 17 Apr 2013 19:10:49 -0000 X-Spam-SWARE-Status: No, score=-5.3 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, KHOP_RCVD_TRUST, KHOP_THREADED, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE autolearn=ham version=3.3.1 X-Spam-User: qpsmtpd, 2 recipients Received: from mail-we0-f181.google.com (HELO mail-we0-f181.google.com) (74.125.82.181) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Wed, 17 Apr 2013 19:10:47 +0000 Received: by mail-we0-f181.google.com with SMTP id r6so1478769wey.40 for ; Wed, 17 Apr 2013 12:10:44 -0700 (PDT) X-Received: by 10.194.123.168 with SMTP id mb8mr13693081wjb.24.1366225844576; Wed, 17 Apr 2013 12:10:44 -0700 (PDT) Received: from localhost.localdomain (arf62-1-82-237-250-248.fbx.proxad.net. [82.237.250.248]) by mx.google.com with ESMTPS id du2sm27363908wib.0.2013.04.17.12.10.42 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 17 Apr 2013 12:10:43 -0700 (PDT) Message-ID: <516EF3B1.2050401@gmail.com> Date: Wed, 17 Apr 2013 21:10:41 +0200 From: =?ISO-8859-1?Q?Fran=E7ois_Dumont?= User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20120829 Thunderbird/15.0 MIME-Version: 1.0 To: "libstdc++@gcc.gnu.org" , gcc-patches Subject: Re: Fix std::pair std::is_copy_assignable behavior References: <51687815.6030507@gmail.com> In-Reply-To: <51687815.6030507@gmail.com> X-Virus-Found: No Hi Here is an other proposal to fix std::is_copy_assignable>. This is not perfect because I have adapted it to current compiler behavior but it is still better than current behavior and enough to commit the unordered C++11 allocator adaptation afterward. It will give me more time to work on the Standard modification proposal to avoid the partial template specialization used for the moment. Thanks to current resolution of DR 1402 we can already define the move assignment operator as default, if deleted the template move assignment operator will be considered and potentially used instead. 2013-04-17 François Dumont * include/bits/stl_pair.h (operator=(const pair&)): Add noexcept qualification. (operator=(pair&&)): Use default implementation. (template<> operator=(const pair&)): Add noexcept qualification. Enable if is_assignable true for both parameter types. (template<> operator=(pair<>&&)): Add noexcept qualification. Enable if is_assignable true for both parameter types. (std::is_copy_assignable<>, std::is_move_assignable<>): Add partial specialization. * testsuite/20_util/pair/is_move_assignable.cc: New. * testsuite/20_util/pair/is_copy_assignable.cc: Likewise. * testsuite/20_util/pair/is_assignable.cc: Likewise. * testsuite/20_util/pair/is_nothrow_move_assignable.cc: Likewise. * testsuite/20_util/pair/assign_neg.cc: Likewise. * testsuite/20_util/pair/is_nothrow_copy_assignable.cc: Likewise. * testsuite/20_util/pair/assign.cc: Likewise. Tested under Linux x86_64. Ok to commit ? François Index: include/bits/stl_pair.h =================================================================== --- include/bits/stl_pair.h (revision 197829) +++ include/bits/stl_pair.h (working copy) @@ -156,6 +156,8 @@ pair& operator=(const pair& __p) + noexcept(__and_, + is_nothrow_copy_assignable<_T2>>::value) { first = __p.first; second = __p.second; @@ -163,18 +165,15 @@ } pair& - operator=(pair&& __p) - noexcept(__and_, - is_nothrow_move_assignable<_T2>>::value) - { - first = std::forward(__p.first); - second = std::forward(__p.second); - return *this; - } + operator=(pair&&) = default; template - pair& + typename enable_if<__and_, + is_assignable<_T2&, const _U2&>>::value, + pair&>::type operator=(const pair<_U1, _U2>& __p) + noexcept(__and_, + is_nothrow_assignable<_T2&, const _U2&>>::value) { first = __p.first; second = __p.second; @@ -182,8 +181,12 @@ } template - pair& + typename enable_if<__and_, + is_assignable<_T2&, _U2&&>>::value, + pair&>::type operator=(pair<_U1, _U2>&& __p) + noexcept(__and_, + is_nothrow_assignable<_T2&, _U2&&>>::value) { first = std::forward<_U1>(__p.first); second = std::forward<_U2>(__p.second); @@ -287,6 +290,19 @@ { return pair<_T1, _T2>(__x, __y); } #endif +#if __cplusplus >= 201103L + template + struct is_copy_assignable> + : public __and_, + std::is_copy_assignable<_T2>>::type + { }; + + template + struct is_move_assignable> + : public __and_, + std::is_move_assignable<_T2>>::type + { }; +#endif /// @} _GLIBCXX_END_NAMESPACE_VERSION Index: testsuite/20_util/pair/is_assignable.cc =================================================================== --- testsuite/20_util/pair/is_assignable.cc (revision 0) +++ testsuite/20_util/pair/is_assignable.cc (revision 0) @@ -0,0 +1,48 @@ +// { dg-do compile } +// { dg-options "-std=c++11" } + +// Copyright (C) 2013 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 + +struct T1 +{ +}; + +struct T2 +{ + T2& + operator=(const T1&); +}; + +typedef std::pair pt1; +typedef std::pair pt2; +typedef std::pair pt3; +typedef std::pair pt4; +typedef std::pair pt5; + +static_assert(std::is_assignable::value, "Error"); +static_assert(std::is_assignable::value, "Error"); +static_assert(std::is_assignable::value, "Error"); +static_assert(!std::is_assignable::value, "Error"); +static_assert(!std::is_assignable::value, "Error"); +static_assert(std::is_assignable::value, "Error"); +static_assert(!std::is_assignable::value, "Error"); + + Index: testsuite/20_util/pair/is_nothrow_move_assignable.cc =================================================================== --- testsuite/20_util/pair/is_nothrow_move_assignable.cc (revision 0) +++ testsuite/20_util/pair/is_nothrow_move_assignable.cc (revision 0) @@ -0,0 +1,57 @@ +// { dg-do compile } +// { dg-options "-std=c++11" } + +// Copyright (C) 2013 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 + +using namespace __gnu_test; + +typedef std::pair pt1; +typedef std::pair pt2; +typedef std::pair pt3; +typedef std::pair pt4; +typedef std::pair pt5; +typedef std::pair pt6; +typedef std::pair pt7; +typedef std::pair pt8; +typedef std::pair pt9; +typedef std::pair pt10; +typedef std::pair pt11; +typedef std::pair pt12; +typedef std::pair pt13; +typedef std::pair pt14; +typedef std::pair pt15; + +static_assert(std::is_nothrow_move_assignable::value, "Error"); +static_assert(std::is_nothrow_move_assignable::value, "Error"); +static_assert(std::is_nothrow_move_assignable::value, "Error"); +static_assert(!std::is_nothrow_move_assignable::value, "Error"); +static_assert(!std::is_nothrow_move_assignable::value, "Error"); +static_assert(!std::is_nothrow_move_assignable::value, "Error"); +static_assert(!std::is_nothrow_move_assignable::value, "Error"); +static_assert(!std::is_nothrow_move_assignable::value, "Error"); +static_assert(std::is_nothrow_move_assignable::value, "Error"); +static_assert(!std::is_nothrow_move_assignable::value, "Error"); +static_assert(!std::is_nothrow_move_assignable::value, "Error"); +static_assert(!std::is_nothrow_move_assignable::value, "Error"); +static_assert(std::is_nothrow_move_assignable::value, "Error"); +static_assert(std::is_nothrow_move_assignable::value, "Error"); +static_assert(!std::is_nothrow_move_assignable::value, "Error"); Index: testsuite/20_util/pair/assign_neg.cc =================================================================== --- testsuite/20_util/pair/assign_neg.cc (revision 0) +++ testsuite/20_util/pair/assign_neg.cc (revision 0) @@ -0,0 +1,30 @@ +// { dg-do compile } +// { dg-options "-std=c++11" } + +// Copyright (C) 2013 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() +{ + std::pair p; + p = p; + p = std::move(p); +} + +// { dg-error "assignment of read-only member" "" { target *-*-* } 162 } Index: testsuite/20_util/pair/is_nothrow_copy_assignable.cc =================================================================== --- testsuite/20_util/pair/is_nothrow_copy_assignable.cc (revision 0) +++ testsuite/20_util/pair/is_nothrow_copy_assignable.cc (revision 0) @@ -0,0 +1,53 @@ +// { dg-do compile } +// { dg-options "-std=c++11" } + +// Copyright (C) 2013 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 + +using namespace __gnu_test; + +typedef std::pair pt1; +typedef std::pair pt2; +typedef std::pair pt3; +typedef std::pair pt4; +typedef std::pair& pt5; +typedef std::pair pt6; +typedef std::pair pt7; +typedef std::pair pt8; +typedef std::pair pt9; +typedef std::pair pt10; +typedef std::pair pt11; +typedef std::pair pt12; +typedef std::pair pt13; + +static_assert(std::is_nothrow_copy_assignable::value, "Error"); +static_assert(std::is_nothrow_copy_assignable::value, "Error"); +static_assert(!std::is_nothrow_copy_assignable::value, "Error"); +static_assert(!std::is_nothrow_copy_assignable::value, "Error"); +static_assert(!std::is_nothrow_copy_assignable::value, "Error"); +static_assert(std::is_nothrow_copy_assignable::value, "Error"); +static_assert(!std::is_nothrow_copy_assignable::value, "Error"); +static_assert(!std::is_nothrow_copy_assignable::value, "Error"); +static_assert(!std::is_nothrow_copy_assignable::value, "Error"); +static_assert(!std::is_nothrow_copy_assignable::value, "Error"); +static_assert(std::is_nothrow_copy_assignable::value, "Error"); +static_assert(std::is_nothrow_copy_assignable::value, "Error"); +static_assert(!std::is_nothrow_copy_assignable::value, "Error"); Index: testsuite/20_util/pair/assign.cc =================================================================== --- testsuite/20_util/pair/assign.cc (revision 0) +++ testsuite/20_util/pair/assign.cc (revision 0) @@ -0,0 +1,177 @@ +// { dg-options "-std=c++11" } + +// Copyright (C) 2013 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 + +void test01() +{ + bool test __attribute__((unused)) = true; + using __gnu_test::counter_type; + + typedef std::pair ptype; + ptype p1(0, 0); + ptype p2(1, 1); + + counter_type::reset(); + + p1 = p2; + + VERIFY( p1.first == 1 ); + VERIFY( p1.second.val == 1 ); + VERIFY( counter_type::copy_assign_count == 1 ); +} + +void test02() +{ + bool test __attribute__((unused)) = true; + using __gnu_test::counter_type; + + typedef std::pair ptype; + ptype p1(0, 0); + ptype p2(1, 1); + + counter_type::reset(); + + p1 = std::move(p2); + + VERIFY( p1.first == 1 ); + VERIFY( p1.second.val == 1 ); + VERIFY( counter_type::move_assign_count == 1 ); +} + +void test03() +{ + bool test __attribute__((unused)) = true; + + typedef std::pair ptype; + int i = 0, j = 1; + ptype p1(i, j); + VERIFY( p1.first == 0 ); + VERIFY( p1.second == 1 ); + + int k = 2, l = 3; + ptype p2(k, l); + VERIFY( p2.first == 2 ); + VERIFY( p2.second == 3 ); + + p1 = p2; + + VERIFY( p1.first == 2 ); + VERIFY( p1.second == 3 ); + VERIFY( p2.first == 2 ); + VERIFY( p2.second == 3 ); + + VERIFY( i == 2 ); + + i = 0; + VERIFY( p1.first == 0 ); +} + +void test04() +{ + bool test __attribute__((unused)) = true; + + typedef std::pair ptype; + int i = 0; + ptype p1(i, 1); + VERIFY( p1.first == 0 ); + VERIFY( p1.second == 1 ); + + int j = 2; + ptype p2(j, 3); + VERIFY( p2.first == 2 ); + VERIFY( p2.second == 3 ); + + p1 = p2; + + VERIFY( p1.first == 2 ); + VERIFY( p1.second == 3 ); + VERIFY( p2.first == 2 ); + VERIFY( p2.second == 3 ); + + VERIFY( i == 2 ); + + i = 0; + VERIFY( p1.first == 0 ); +} + +namespace __gnu_test +{ + struct MyStruct + { + int _i; + + MyStruct() + : _i() { } + MyStruct(int i) + : _i(i) { } + MyStruct(const MyStruct& other) + : _i(other._i) { } + MyStruct(MyStruct&& other) + : _i(other._i) + { other._i = -1; } + + MyStruct& + operator=(const MyStruct& other) + { _i = other._i; } + + MyStruct& + operator=(MyStruct&& other) + { + _i = other._i; + other._i = -1; + } + }; +} + +void test05() +{ + bool test __attribute__((unused)) = true; + + typedef std::pair<__gnu_test::MyStruct, __gnu_test::MyStruct> ptype1; + typedef std::pair<__gnu_test::MyStruct, const __gnu_test::MyStruct> ptype2; + + static_assert(std::is_move_assignable::value, "Error"); + static_assert(!std::is_move_assignable::value, "Error"); + static_assert(std::is_assignable::value, "Error"); + + ptype1 p1(1, 2); + ptype2 p2(3, 4); + + p1 = std::move(p2); + + VERIFY( p1.first._i == 3 ); + VERIFY( p1.second._i == 4 ); + VERIFY( p2.first._i == -1 ); + VERIFY( p2.second._i == 4 ); +} + +int main() +{ + test01(); + test02(); + test03(); + test04(); + test05(); + return 0; +} Index: testsuite/20_util/pair/is_move_assignable.cc =================================================================== --- testsuite/20_util/pair/is_move_assignable.cc (revision 0) +++ testsuite/20_util/pair/is_move_assignable.cc (revision 0) @@ -0,0 +1,59 @@ +// { dg-do compile } +// { dg-options "-std=c++11" } + +// Copyright (C) 2013 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 + +using namespace __gnu_test; + +typedef std::pair pt1; +typedef std::pair pt2; +typedef std::pair pt3; +typedef std::pair pt4; +typedef std::pair pt5; +typedef std::pair pt6; +typedef std::pair pt7; +typedef std::pair pt8; +typedef std::pair pt9; +typedef std::pair pt10; +typedef std::pair pt11; +typedef std::pair pt12; +typedef std::pair pt13; +typedef std::pair pt14; +typedef std::pair pt15; +typedef std::pair pt16; + +static_assert(std::is_move_assignable::value, "Error"); +static_assert(std::is_move_assignable::value, "Error"); +static_assert(std::is_move_assignable::value, "Error"); +static_assert(std::is_move_assignable::value, "Error"); +static_assert(std::is_move_assignable::value, "Error"); +static_assert(std::is_move_assignable::value, "Error"); +static_assert(!std::is_move_assignable::value, "Error"); +static_assert(!std::is_move_assignable::value, "Error"); +static_assert(std::is_move_assignable::value, "Error"); +static_assert(std::is_move_assignable::value, "Error"); +static_assert(std::is_move_assignable::value, "Error"); +static_assert(!std::is_move_assignable::value, "Error"); +static_assert(!std::is_move_assignable::value, "Error"); +static_assert(!std::is_move_assignable::value, "Error"); +static_assert(std::is_move_assignable::value, "Error"); +static_assert(!std::is_move_assignable::value, "Error"); Index: testsuite/20_util/pair/is_copy_assignable.cc =================================================================== --- testsuite/20_util/pair/is_copy_assignable.cc (revision 0) +++ testsuite/20_util/pair/is_copy_assignable.cc (revision 0) @@ -0,0 +1,53 @@ +// { dg-do compile } +// { dg-options "-std=c++11" } + +// Copyright (C) 2013 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 + +using namespace __gnu_test; + +typedef std::pair pt1; +typedef std::pair pt2; +typedef std::pair pt3; +typedef std::pair pt4; +//typedef std::pair& pt5; +typedef std::pair pt6; +typedef std::pair pt7; +typedef std::pair pt8; +typedef std::pair pt9; +typedef std::pair pt10; +typedef std::pair pt11; +typedef std::pair pt12; +typedef std::pair pt13; + +static_assert(std::is_copy_assignable::value, "Error"); +static_assert(std::is_copy_assignable::value, "Error"); +static_assert(!std::is_copy_assignable::value, "Error"); +static_assert(!std::is_copy_assignable::value, "Error"); +//static_assert(!std::is_copy_assignable::value, "Error"); +static_assert(std::is_copy_assignable::value, "Error"); +static_assert(std::is_copy_assignable::value, "Error"); +static_assert(std::is_copy_assignable::value, "Error"); +static_assert(std::is_copy_assignable::value, "Error"); +static_assert(!std::is_copy_assignable::value, "Error"); +static_assert(std::is_copy_assignable::value, "Error"); +static_assert(std::is_copy_assignable::value, "Error"); +static_assert(!std::is_copy_assignable::value, "Error");