[{"id":1765467,"web_url":"http://patchwork.ozlabs.org/comment/1765467/","msgid":"<20170908155011.GE4582@redhat.com>","list_archive_url":null,"date":"2017-09-08T15:50:11","subject":"Re: Rb_tree constructor optimization","submitter":{"id":48004,"url":"http://patchwork.ozlabs.org/api/people/48004/","name":"Jonathan Wakely","email":"jwakely@redhat.com"},"content":"On 28/08/17 21:12 +0200, François Dumont wrote:\n>Hi\n>\n>    Here is the always equal allocator optimization for associative \n>containers.\n>\n>    Tested under Linux x86_64.\n>\n>    * include/bits/stl_tree.h\n>    (_Rb_tree_impl(_Rb_tree_impl&&, _Node_allocator&&)): New.\n>    (_Rb_tree(_Rb_tree&&, _Node_allocator&&, std::true_type)): New.\n>    (_Rb_tree(_Rb_tree&&, _Node_allocator&&, std::false_type)): Likewise.\n>    (_Rb_tree(_Rb_tree&&, _Node_allocator&&)): Adapt, use latters.\n>\n>    Ok to apply ?\n>\n>François\n>\n>\n\n>diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h\n>index c2417f1..f7d34e3 100644\n>--- a/libstdc++-v3/include/bits/stl_tree.h\n>+++ b/libstdc++-v3/include/bits/stl_tree.h\n>@@ -704,6 +704,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n> #else\n> \t  _Rb_tree_impl(_Rb_tree_impl&&) = default;\n> \n>+\t  _Rb_tree_impl(_Rb_tree_impl&& __x, _Node_allocator&& __a) noexcept\n\nThis is an unconditional noexcept, but ...\n\n>+\t    : _Node_allocator(std::move(__a)),\n>+\t      _Base_key_compare(std::move(__x)),\n\nThis constructor has a conditional noexcept. That's a bug.\n\n>+\t      _Rb_tree_header(std::move(__x))\n>+\t  { }\n\nHowever, I don't think we need this new constructor anyway, see below.\n\n> \t  _Rb_tree_impl(const _Key_compare& __comp, _Node_allocator&& __a)\n> \t  : _Node_allocator(std::move(__a)), _Base_key_compare(__comp)\n> \t  { }\n>@@ -947,7 +953,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n>       : _Rb_tree(std::move(__x), _Node_allocator(__a))\n>       { }\n> \n>-      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a);\n>+    private:\n>+      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, std::true_type) noexcept\n\nThis noexcept should be conditional.\n\n>+      : _M_impl(std::move(__x._M_impl), std::move(__a))\n>+      { }\n\nSince we know __a == __x.get_allocator() we could just do:\n\n      _Rb_tree(_Rb_tree&& __x, _Node_allocator&&, true_type)\n      noexcept(is_nothrow_move_constructible<_Rb_tree_impl<_Compare>>::value)\n      : _M_impl(std::move(__x._M_impl))\n      { }\n\nThis means we don't need the new constructor.\n\nOr equivalently, just delegate to the move constructor:\n\n      _Rb_tree(_Rb_tree&& __x, _Node_allocator&&, true_type)\n      noexcept(is_nothrow_move_constructible<_Rb_tree>::value)\n      : _Rb_tree(std::move(__x))\n      { }\n\n>+      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, std::false_type);\n>+\n>+    public:\n>+      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a)\n>+      : _Rb_tree(std::move(__x), std::move(__a),\n>+\t\t typename _Alloc_traits::is_always_equal{})\n>+      { }\n> #endif\n> \n>       ~_Rb_tree() _GLIBCXX_NOEXCEPT\n>@@ -1591,12 +1608,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n>   template<typename _Key, typename _Val, typename _KeyOfValue,\n> \t   typename _Compare, typename _Alloc>\n>     _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::\n>-    _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a)\n>+    _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, std::false_type __eq)\n>     : _M_impl(__x._M_impl._M_key_compare, std::move(__a))\n>     {\n>-      using __eq = typename _Alloc_traits::is_always_equal;\n>       if (__x._M_root() != nullptr)\n>-\t_M_move_data(__x, __eq());\n>+\t_M_move_data(__x, __eq);\n>     }\n\nI think this constructor is simple enough that it should be defined\nin-class, so it's inline.\n\nThere's no need to qualify true_type and false_type with the std\nnamespace (I don't know why some of the existing code does that).","headers":{"Return-Path":"<gcc-patches-return-461732-incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list gcc-patches@gcc.gnu.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=gcc-patches-return-461732-incoming=patchwork.ozlabs.org@gcc.gnu.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (1024-bit key;\n\tunprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org\n\theader.b=\"ZtxorOCf\"; dkim-atps=neutral","sourceware.org; auth=none","ext-mx05.extmail.prod.ext.phx2.redhat.com;\n\tdmarc=none (p=none dis=none) header.from=redhat.com","ext-mx05.extmail.prod.ext.phx2.redhat.com;\n\tspf=fail smtp.mailfrom=jwakely@redhat.com"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xphc01rLCz9s7f\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat,  9 Sep 2017 01:50:23 +1000 (AEST)","(qmail 17306 invoked by alias); 8 Sep 2017 15:50:15 -0000","(qmail 17046 invoked by uid 89); 8 Sep 2017 15:50:14 -0000","from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by\n\tsourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP;\n\tFri, 08 Sep 2017 15:50:13 +0000","from smtp.corp.redhat.com\n\t(int-mx06.intmail.prod.int.phx2.redhat.com\n\t[10.5.11.16])\t(using TLSv1.2 with cipher AECDH-AES256-SHA\n\t(256/256 bits))\t(No client certificate requested)\tby\n\tmx1.redhat.com (Postfix) with ESMTPS id 6166E750;\n\tFri,  8 Sep 2017 15:50:12 +0000 (UTC)","from localhost (unknown [10.33.36.109])\tby smtp.corp.redhat.com\n\t(Postfix) with ESMTP id DD4EA5C882;\n\tFri,  8 Sep 2017 15:50:11 +0000 (UTC)"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender:date\n\t:from:to:cc:subject:message-id:references:mime-version\n\t:content-type:content-transfer-encoding:in-reply-to; q=dns; s=\n\tdefault; b=Os6SSkie4egpzDEv051BMpyH3mi9hxmRIk+YLaHP+VjBZtHmXOYQn\n\tbIMX9X/3QlzVR1aIYVzn2NW270ARJBO7xWGHYwRctXOeYUA9fro7QqFXcCXQ+wud\n\te+7p+i8/QZYjO0jhtFabMGwHNY78L2YuDKyht2wMuADdO3weKYcvhE=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender:date\n\t:from:to:cc:subject:message-id:references:mime-version\n\t:content-type:content-transfer-encoding:in-reply-to; s=default;\n\tbh=tQ5a3jU9jjjBhxzTs7H4h5OHeRs=; b=ZtxorOCfxfIdOg2pKxBfo2LHXRv5\n\tZ815dgrGHBrO0UT4hDjjT+KDNDa6V3kiK4k4aVGEBSEohoreWjr0vBMby1fHdJCI\n\tiUuXCbOX/wBrE1RdBUmhVwyOtEVNJ6mefYFNGc0Smiyn3WosrExcTKPGYNPQ23Fp\n\t7WFjHpd9uTwRNv8=","Mailing-List":"contact gcc-patches-help@gcc.gnu.org; run by ezmlm","Precedence":"bulk","List-Id":"<gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<mailto:gcc-patches-unsubscribe-incoming=patchwork.ozlabs.org@gcc.gnu.org>","List-Archive":"<http://gcc.gnu.org/ml/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-help@gcc.gnu.org>","Sender":"gcc-patches-owner@gcc.gnu.org","X-Virus-Found":"No","X-Spam-SWARE-Status":"No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0,\n\tGIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD,\n\tSPF_HELO_PASS autolearn=ham version=3.3.2\n\tspammy=HContent-Transfer-Encoding:8bit","X-Spam-User":"qpsmtpd, 2 recipients","X-HELO":"mx1.redhat.com","DMARC-Filter":"OpenDMARC Filter v1.3.2 mx1.redhat.com 6166E750","Date":"Fri, 8 Sep 2017 16:50:11 +0100","From":"Jonathan Wakely <jwakely@redhat.com>","To":"=?iso-8859-1?q?Fran=E7ois?= Dumont <frs.dumont@gmail.com>","Cc":"\"libstdc++@gcc.gnu.org\" <libstdc++@gcc.gnu.org>,\n\tgcc-patches <gcc-patches@gcc.gnu.org>","Subject":"Re: Rb_tree constructor optimization","Message-ID":"<20170908155011.GE4582@redhat.com>","References":"<4026eacd-cb49-e756-c855-627cd5a40206@gmail.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=iso-8859-1; format=flowed","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<4026eacd-cb49-e756-c855-627cd5a40206@gmail.com>","X-Clacks-Overhead":"GNU Terry Pratchett","User-Agent":"Mutt/1.8.3 (2017-05-23)"}},{"id":1768109,"web_url":"http://patchwork.ozlabs.org/comment/1768109/","msgid":"<f17199f2-c565-c8aa-e24b-10843785cf55@gmail.com>","list_archive_url":null,"date":"2017-09-13T19:57:25","subject":"Re: Rb_tree constructor optimization","submitter":{"id":9231,"url":"http://patchwork.ozlabs.org/api/people/9231/","name":"François Dumont","email":"frs.dumont@gmail.com"},"content":"On 08/09/2017 17:50, Jonathan Wakely wrote:\n>\n> Since we know __a == __x.get_allocator() we could just do:\n>\n>      _Rb_tree(_Rb_tree&& __x, _Node_allocator&&, true_type)\n> noexcept(is_nothrow_move_constructible<_Rb_tree_impl<_Compare>>::value)\n>      : _M_impl(std::move(__x._M_impl))\n>      { }\n>\n> This means we don't need the new constructor.\n\n     You want to consider that a always equal allocator is stateless and \nso that the provided allocator rvalue reference do not need to be moved. \nIMHO you can have allocator with state that do not participate in \ncomparison like some monitoring info.\n\n     I'm not confortable with that and prefer to keep current behavior \nso I propose this new patch considering all your other remarks.\n\n     I change noexcept qualification on [multi]map/set constructors to \njust rely on _Rep_type constructor noexcept qualification to not \nduplicate it.\n\nFrançois\ndiff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h\nindex 0e8a98a..cdd2e7c 100644\n--- a/libstdc++-v3/include/bits/stl_map.h\n+++ b/libstdc++-v3/include/bits/stl_map.h\n@@ -235,8 +235,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \n       /// Allocator-extended move constructor.\n       map(map&& __m, const allocator_type& __a)\n-      noexcept(is_nothrow_copy_constructible<_Compare>::value\n-\t       && _Alloc_traits::_S_always_equal())\n+      noexcept( noexcept(\n+\t_Rep_type(declval<_Rep_type>(), declval<_Pair_alloc_type>())) )\n       : _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { }\n \n       /// Allocator-extended initialier-list constructor.\ndiff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h\nindex 7e3cea4..d32104d 100644\n--- a/libstdc++-v3/include/bits/stl_multimap.h\n+++ b/libstdc++-v3/include/bits/stl_multimap.h\n@@ -232,8 +232,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \n       /// Allocator-extended move constructor.\n       multimap(multimap&& __m, const allocator_type& __a)\n-      noexcept(is_nothrow_copy_constructible<_Compare>::value\n-\t       && _Alloc_traits::_S_always_equal())\n+      noexcept( noexcept(\n+\t_Rep_type(declval<_Rep_type>(), declval<_Pair_alloc_type>())) )\n       : _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { }\n \n       /// Allocator-extended initialier-list constructor.\ndiff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h\nindex 517e77e..9ab4ab7 100644\n--- a/libstdc++-v3/include/bits/stl_multiset.h\n+++ b/libstdc++-v3/include/bits/stl_multiset.h\n@@ -244,8 +244,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \n       /// Allocator-extended move constructor.\n       multiset(multiset&& __m, const allocator_type& __a)\n-      noexcept(is_nothrow_copy_constructible<_Compare>::value\n-\t       && _Alloc_traits::_S_always_equal())\n+      noexcept( noexcept(\n+\t_Rep_type(declval<_Rep_type>(), declval<_Key_alloc_type>())) )\n       : _M_t(std::move(__m._M_t), _Key_alloc_type(__a)) { }\n \n       /// Allocator-extended initialier-list constructor.\ndiff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h\nindex e804a7c..6b64bcd 100644\n--- a/libstdc++-v3/include/bits/stl_set.h\n+++ b/libstdc++-v3/include/bits/stl_set.h\n@@ -248,8 +248,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \n       /// Allocator-extended move constructor.\n       set(set&& __x, const allocator_type& __a)\n-      noexcept(is_nothrow_copy_constructible<_Compare>::value\n-\t       && _Alloc_traits::_S_always_equal())\n+      noexcept( noexcept(\n+\t_Rep_type(declval<_Rep_type>(), declval<_Key_alloc_type>())) )\n       : _M_t(std::move(__x._M_t), _Key_alloc_type(__a)) { }\n \n       /// Allocator-extended initialier-list constructor.\ndiff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h\nindex c2417f1..7aacc24 100644\n--- a/libstdc++-v3/include/bits/stl_tree.h\n+++ b/libstdc++-v3/include/bits/stl_tree.h\n@@ -704,6 +704,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n #else\n \t  _Rb_tree_impl(_Rb_tree_impl&&) = default;\n \n+\t  _Rb_tree_impl(_Rb_tree_impl&& __x, _Node_allocator&& __a)\n+\t  : _Node_allocator(std::move(__a)),\n+\t    _Base_key_compare(std::move(__x)),\n+\t    _Rb_tree_header(std::move(__x))\n+\t  { }\n+\n \t  _Rb_tree_impl(const _Key_compare& __comp, _Node_allocator&& __a)\n \t  : _Node_allocator(std::move(__a)), _Base_key_compare(__comp)\n \t  { }\n@@ -947,7 +953,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n       : _Rb_tree(std::move(__x), _Node_allocator(__a))\n       { }\n \n-      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a);\n+    private:\n+      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, true_type)\n+      : _M_impl(std::move(__x._M_impl), std::move(__a))\n+      { }\n+\n+      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, false_type)\n+      : _M_impl(__x._M_impl._M_key_compare, std::move(__a))\n+      {\n+\tif (__x._M_root() != nullptr)\n+\t  _M_move_data(__x, false_type{});\n+      }\n+\n+    public:\n+      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a)\n+      noexcept(is_nothrow_move_constructible<_Rb_tree_impl<_Compare>>::value\n+\t       && _Alloc_traits::_S_always_equal())\n+      : _Rb_tree(std::move(__x), std::move(__a),\n+\t\t typename _Alloc_traits::is_always_equal{})\n+      { }\n #endif\n \n       ~_Rb_tree() _GLIBCXX_NOEXCEPT\n@@ -1347,22 +1371,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n     private:\n       // Move elements from container with equal allocator.\n       void\n-      _M_move_data(_Rb_tree& __x, std::true_type)\n+      _M_move_data(_Rb_tree& __x, true_type)\n       { _M_impl._M_move_data(__x._M_impl); }\n \n       // Move elements from container with possibly non-equal allocator,\n       // which might result in a copy not a move.\n       void\n-      _M_move_data(_Rb_tree&, std::false_type);\n+      _M_move_data(_Rb_tree&, false_type);\n \n       // Move assignment from container with equal allocator.\n       void\n-      _M_move_assign(_Rb_tree&, std::true_type);\n+      _M_move_assign(_Rb_tree&, true_type);\n \n       // Move assignment from container with possibly non-equal allocator,\n       // which might result in a copy not a move.\n       void\n-      _M_move_assign(_Rb_tree&, std::false_type);\n+      _M_move_assign(_Rb_tree&, false_type);\n #endif\n \n #if __cplusplus > 201402L\n@@ -1590,23 +1614,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n #if __cplusplus >= 201103L\n   template<typename _Key, typename _Val, typename _KeyOfValue,\n \t   typename _Compare, typename _Alloc>\n-    _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::\n-    _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a)\n-    : _M_impl(__x._M_impl._M_key_compare, std::move(__a))\n-    {\n-      using __eq = typename _Alloc_traits::is_always_equal;\n-      if (__x._M_root() != nullptr)\n-\t_M_move_data(__x, __eq());\n-    }\n-\n-  template<typename _Key, typename _Val, typename _KeyOfValue,\n-\t   typename _Compare, typename _Alloc>\n     void\n     _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::\n-    _M_move_data(_Rb_tree& __x, std::false_type)\n+    _M_move_data(_Rb_tree& __x, false_type)\n     {\n       if (_M_get_Node_allocator() == __x._M_get_Node_allocator())\n-\t_M_move_data(__x, std::true_type());\n+\t_M_move_data(__x, true_type());\n       else\n \t{\n \t  _Alloc_node __an(*this);\n@@ -1628,7 +1641,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n     {\n       clear();\n       if (__x._M_root() != nullptr)\n-\t_M_move_data(__x, std::true_type());\n+\t_M_move_data(__x, true_type());\n       std::__alloc_on_move(_M_get_Node_allocator(),\n \t\t\t   __x._M_get_Node_allocator());\n     }","headers":{"Return-Path":"<gcc-patches-return-462078-incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list gcc-patches@gcc.gnu.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=gcc-patches-return-462078-incoming=patchwork.ozlabs.org@gcc.gnu.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (1024-bit key;\n\tunprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org\n\theader.b=\"ycp+2BQm\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xsss75NFNz9s3T\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 14 Sep 2017 05:57:47 +1000 (AEST)","(qmail 49956 invoked by alias); 13 Sep 2017 19:57:33 -0000","(qmail 49937 invoked by uid 89); 13 Sep 2017 19:57:31 -0000","from mail-wm0-f46.google.com (HELO mail-wm0-f46.google.com)\n\t(74.125.82.46) by sourceware.org\n\t(qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP;\n\tWed, 13 Sep 2017 19:57:29 +0000","by mail-wm0-f46.google.com with SMTP id 189so459741wmh.1;\n\tWed, 13 Sep 2017 12:57:29 -0700 (PDT)","from [192.168.0.23] (arf62-1-82-237-250-248.fbx.proxad.net.\n\t[82.237.250.248]) by smtp.googlemail.com with ESMTPSA id\n\tl15sm3092423wmd.23.2017.09.13.12.57.26 (version=TLS1_2\n\tcipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tWed, 13 Sep 2017 12:57:26 -0700 (PDT)"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender:from\n\t:subject:to:cc:references:message-id:date:mime-version\n\t:in-reply-to:content-type; q=dns; s=default; b=jHsJoU3w4bbHoQ/lL\n\tdVPesjxzHJFy1/2nUjDvrIbeGqn5PK7Ozs48JIb0/U9eJ1+/sPzmsZ8XYcnBsz8v\n\tN8W1/owhJwd6LcNtsLwjphWMBgRHpHkskjIGBm6i4N1f5W3NfI9LGi6zTUloAPZh\n\t4+nfE03m8eyY3oH2cZwwHI9mtk=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender:from\n\t:subject:to:cc:references:message-id:date:mime-version\n\t:in-reply-to:content-type; s=default; bh=irGRvVTiiEmHG1Df1XJljQj\n\tuNqw=; b=ycp+2BQmvEyM6S2Qsjb8fcWcJzMrhqhQzTkx0XRGo/AvRuMakw7uyM2\n\tj/J7KOy8JaRw7RY/u3cBbfkZ5jAswNiYebEXvuLTo/f+BoDEgyS7INebixSKfvm/\n\tMfTmmMLKQTzmTeVVlXmUgBmiW+jed57dR90f3KjDg6DI/vFlmCcU=","Mailing-List":"contact gcc-patches-help@gcc.gnu.org; run by ezmlm","Precedence":"bulk","List-Id":"<gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<mailto:gcc-patches-unsubscribe-incoming=patchwork.ozlabs.org@gcc.gnu.org>","List-Archive":"<http://gcc.gnu.org/ml/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-help@gcc.gnu.org>","Sender":"gcc-patches-owner@gcc.gnu.org","X-Virus-Found":"No","X-Spam-SWARE-Status":"No, score=-24.5 required=5.0 tests=AWL, BAYES_00,\n\tFREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2,\n\tGIT_PATCH_3, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM,\n\tSPF_PASS autolearn=ham version=3.3.2 spammy=","X-Spam-User":"qpsmtpd, 2 recipients","X-HELO":"mail-wm0-f46.google.com","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net;\n\ts=20161025;\n\th=x-gm-message-state:from:subject:to:cc:references:message-id:date\n\t:user-agent:mime-version:in-reply-to:content-language;\n\tbh=VZ+RvdmGysLF/ojS/yDH3DCrdEqU448xpKlFcIcrCpQ=;\n\tb=DMQH2+B/SOMGkze4BAXKk9mFTSgtasNvKy9oz4EG4J3e2HAtF5+XtpHWfE/OwRijxi\n\t9DC3OahCvQ/EnWrJM2RMi53vnaU77mULyhZ+3HddD7UFgDGE+HHYK6CWP9pWT6gJ9j8p\n\tnevo6m/toApbDYC15KshIrzUtxXa3ps8nOGVHR/FnGpeRlS3Yi0eEwBvI2y7uDSsnpO1\n\tZ3TkXgfr2Y6pZ3LKTZz4E8I86l8Dyo8AtIp2wgKAFb2yoHYhB1qF/0TdXwAp46s0YpoZ\n\t7Vy5mwy6ickf3VjYD9M+xht1dhePanapQCyg+wrFH6leytteFf5EhmiX/L3S3mEsWm/P\n\twbWA==","X-Gm-Message-State":"AHPjjUiCnSurq6JqX1RF5jnxUSHSj52EVagHwERReBR4krFkqOm6YCE2\tdj7YOkz4BnU3q8HUBMNMY8V9Kg==","X-Google-Smtp-Source":"AOwi7QDr/hMPCQTv/FgDbM+I1OxhCbnFk2X+hbDEPMWhV8HrFiB8A5l2g8D+CwrW790vzr+GMCNTcQ==","X-Received":"by 10.28.39.71 with SMTP id n68mr3851642wmn.114.1505332647568;\n\tWed, 13 Sep 2017 12:57:27 -0700 (PDT)","From":"=?utf-8?q?Fran=C3=A7ois_Dumont?= <frs.dumont@gmail.com>","Subject":"Re: Rb_tree constructor optimization","To":"Jonathan Wakely <jwakely@redhat.com>","Cc":"\"libstdc++@gcc.gnu.org\" <libstdc++@gcc.gnu.org>,\n\tgcc-patches <gcc-patches@gcc.gnu.org>","References":"<4026eacd-cb49-e756-c855-627cd5a40206@gmail.com>\n\t<20170908155011.GE4582@redhat.com>","Message-ID":"<f17199f2-c565-c8aa-e24b-10843785cf55@gmail.com>","Date":"Wed, 13 Sep 2017 21:57:25 +0200","User-Agent":"Mozilla/5.0 (X11; Linux x86_64;\n\trv:52.0) Gecko/20100101 Thunderbird/52.2.1","MIME-Version":"1.0","In-Reply-To":"<20170908155011.GE4582@redhat.com>","Content-Type":"multipart/mixed;\n\tboundary=\"------------CF3E11DBA6853B94FC97585C\""}},{"id":1768813,"web_url":"http://patchwork.ozlabs.org/comment/1768813/","msgid":"<5f54e6fb-0394-d13b-0e62-617cf0a2dbed@gmail.com>","list_archive_url":null,"date":"2017-09-14T20:04:19","subject":"Re: Rb_tree constructor optimization","submitter":{"id":9231,"url":"http://patchwork.ozlabs.org/api/people/9231/","name":"François Dumont","email":"frs.dumont@gmail.com"},"content":"I realized there was no test on the noexcept qualification of the move \nconstructor with allocator.\n\nI added some and found out that patch was missing a noexcept \nqualification at _Rb_tree level.\n\nHere is the updated patch fully tested, ok to commit ?\n\nFrançois\n\n\nOn 13/09/2017 21:57, François Dumont wrote:\n> On 08/09/2017 17:50, Jonathan Wakely wrote:\n>>\n>> Since we know __a == __x.get_allocator() we could just do:\n>>\n>>      _Rb_tree(_Rb_tree&& __x, _Node_allocator&&, true_type)\n>> noexcept(is_nothrow_move_constructible<_Rb_tree_impl<_Compare>>::value)\n>>      : _M_impl(std::move(__x._M_impl))\n>>      { }\n>>\n>> This means we don't need the new constructor.\n>\n>     You want to consider that a always equal allocator is stateless \n> and so that the provided allocator rvalue reference do not need to be \n> moved. IMHO you can have allocator with state that do not participate \n> in comparison like some monitoring info.\n>\n>     I'm not confortable with that and prefer to keep current behavior \n> so I propose this new patch considering all your other remarks.\n>\n>     I change noexcept qualification on [multi]map/set constructors to \n> just rely on _Rep_type constructor noexcept qualification to not \n> duplicate it.\n>\n> François\n>\n>\ndiff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h\nindex 0e8a98a..cdd2e7c 100644\n--- a/libstdc++-v3/include/bits/stl_map.h\n+++ b/libstdc++-v3/include/bits/stl_map.h\n@@ -235,8 +235,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \n       /// Allocator-extended move constructor.\n       map(map&& __m, const allocator_type& __a)\n-      noexcept(is_nothrow_copy_constructible<_Compare>::value\n-\t       && _Alloc_traits::_S_always_equal())\n+      noexcept( noexcept(\n+\t_Rep_type(declval<_Rep_type>(), declval<_Pair_alloc_type>())) )\n       : _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { }\n \n       /// Allocator-extended initialier-list constructor.\ndiff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h\nindex 7e3cea4..d32104d 100644\n--- a/libstdc++-v3/include/bits/stl_multimap.h\n+++ b/libstdc++-v3/include/bits/stl_multimap.h\n@@ -232,8 +232,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \n       /// Allocator-extended move constructor.\n       multimap(multimap&& __m, const allocator_type& __a)\n-      noexcept(is_nothrow_copy_constructible<_Compare>::value\n-\t       && _Alloc_traits::_S_always_equal())\n+      noexcept( noexcept(\n+\t_Rep_type(declval<_Rep_type>(), declval<_Pair_alloc_type>())) )\n       : _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { }\n \n       /// Allocator-extended initialier-list constructor.\ndiff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h\nindex 517e77e..9ab4ab7 100644\n--- a/libstdc++-v3/include/bits/stl_multiset.h\n+++ b/libstdc++-v3/include/bits/stl_multiset.h\n@@ -244,8 +244,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \n       /// Allocator-extended move constructor.\n       multiset(multiset&& __m, const allocator_type& __a)\n-      noexcept(is_nothrow_copy_constructible<_Compare>::value\n-\t       && _Alloc_traits::_S_always_equal())\n+      noexcept( noexcept(\n+\t_Rep_type(declval<_Rep_type>(), declval<_Key_alloc_type>())) )\n       : _M_t(std::move(__m._M_t), _Key_alloc_type(__a)) { }\n \n       /// Allocator-extended initialier-list constructor.\ndiff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h\nindex e804a7c..6b64bcd 100644\n--- a/libstdc++-v3/include/bits/stl_set.h\n+++ b/libstdc++-v3/include/bits/stl_set.h\n@@ -248,8 +248,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \n       /// Allocator-extended move constructor.\n       set(set&& __x, const allocator_type& __a)\n-      noexcept(is_nothrow_copy_constructible<_Compare>::value\n-\t       && _Alloc_traits::_S_always_equal())\n+      noexcept( noexcept(\n+\t_Rep_type(declval<_Rep_type>(), declval<_Key_alloc_type>())) )\n       : _M_t(std::move(__x._M_t), _Key_alloc_type(__a)) { }\n \n       /// Allocator-extended initialier-list constructor.\ndiff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h\nindex c2417f1..ebfc3f9 100644\n--- a/libstdc++-v3/include/bits/stl_tree.h\n+++ b/libstdc++-v3/include/bits/stl_tree.h\n@@ -704,6 +704,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n #else\n \t  _Rb_tree_impl(_Rb_tree_impl&&) = default;\n \n+\t  _Rb_tree_impl(_Rb_tree_impl&& __x, _Node_allocator&& __a)\n+\t  : _Node_allocator(std::move(__a)),\n+\t    _Base_key_compare(std::move(__x)),\n+\t    _Rb_tree_header(std::move(__x))\n+\t  { }\n+\n \t  _Rb_tree_impl(const _Key_compare& __comp, _Node_allocator&& __a)\n \t  : _Node_allocator(std::move(__a)), _Base_key_compare(__comp)\n \t  { }\n@@ -944,10 +950,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n       _Rb_tree(_Rb_tree&&) = default;\n \n       _Rb_tree(_Rb_tree&& __x, const allocator_type& __a)\n+      noexcept( noexcept(\n+\t_Rb_tree(declval<_Rb_tree>(), declval<_Node_allocator>())) )\n       : _Rb_tree(std::move(__x), _Node_allocator(__a))\n       { }\n \n-      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a);\n+    private:\n+      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, true_type)\n+      noexcept(is_nothrow_move_constructible<_Rb_tree_impl<_Compare>>::value)\n+      : _M_impl(std::move(__x._M_impl), std::move(__a))\n+      { }\n+\n+      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, false_type)\n+      : _M_impl(__x._M_impl._M_key_compare, std::move(__a))\n+      {\n+\tif (__x._M_root() != nullptr)\n+\t  _M_move_data(__x, false_type{});\n+      }\n+\n+    public:\n+      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a)\n+      noexcept( noexcept(\n+\t_Rb_tree(declval<_Rb_tree>(), declval<_Node_allocator>(),\n+\t\t declval<typename _Alloc_traits::is_always_equal>()) ) )\n+      : _Rb_tree(std::move(__x), std::move(__a),\n+\t\t typename _Alloc_traits::is_always_equal{})\n+      { }\n #endif\n \n       ~_Rb_tree() _GLIBCXX_NOEXCEPT\n@@ -1347,22 +1375,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n     private:\n       // Move elements from container with equal allocator.\n       void\n-      _M_move_data(_Rb_tree& __x, std::true_type)\n+      _M_move_data(_Rb_tree& __x, true_type)\n       { _M_impl._M_move_data(__x._M_impl); }\n \n       // Move elements from container with possibly non-equal allocator,\n       // which might result in a copy not a move.\n       void\n-      _M_move_data(_Rb_tree&, std::false_type);\n+      _M_move_data(_Rb_tree&, false_type);\n \n       // Move assignment from container with equal allocator.\n       void\n-      _M_move_assign(_Rb_tree&, std::true_type);\n+      _M_move_assign(_Rb_tree&, true_type);\n \n       // Move assignment from container with possibly non-equal allocator,\n       // which might result in a copy not a move.\n       void\n-      _M_move_assign(_Rb_tree&, std::false_type);\n+      _M_move_assign(_Rb_tree&, false_type);\n #endif\n \n #if __cplusplus > 201402L\n@@ -1590,23 +1618,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n #if __cplusplus >= 201103L\n   template<typename _Key, typename _Val, typename _KeyOfValue,\n \t   typename _Compare, typename _Alloc>\n-    _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::\n-    _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a)\n-    : _M_impl(__x._M_impl._M_key_compare, std::move(__a))\n-    {\n-      using __eq = typename _Alloc_traits::is_always_equal;\n-      if (__x._M_root() != nullptr)\n-\t_M_move_data(__x, __eq());\n-    }\n-\n-  template<typename _Key, typename _Val, typename _KeyOfValue,\n-\t   typename _Compare, typename _Alloc>\n     void\n     _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::\n-    _M_move_data(_Rb_tree& __x, std::false_type)\n+    _M_move_data(_Rb_tree& __x, false_type)\n     {\n       if (_M_get_Node_allocator() == __x._M_get_Node_allocator())\n-\t_M_move_data(__x, std::true_type());\n+\t_M_move_data(__x, true_type());\n       else\n \t{\n \t  _Alloc_node __an(*this);\n@@ -1628,7 +1645,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n     {\n       clear();\n       if (__x._M_root() != nullptr)\n-\t_M_move_data(__x, std::true_type());\n+\t_M_move_data(__x, true_type());\n       std::__alloc_on_move(_M_get_Node_allocator(),\n \t\t\t   __x._M_get_Node_allocator());\n     }\ndiff --git a/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_move_construct.cc\nindex b172df7..97c1a47 100644\n--- a/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_move_construct.cc\n+++ b/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_move_construct.cc\n@@ -23,4 +23,25 @@\n \n typedef std::map<int, int> mtype;\n \n-static_assert(std::is_nothrow_move_constructible<mtype>::value, \"Error\");\n+static_assert( std::is_nothrow_move_constructible<mtype>::value,\n+\t       \"noexcept move constructor\" );\n+static_assert( noexcept( mtype(std::declval<mtype>(),\n+\t\tstd::declval<const typename mtype::allocator_type&>()) ),\n+\t       \"noexcept move constructor with allocator\" );\n+\n+struct ExceptLess\n+{\n+  ExceptLess() = default;\n+  ExceptLess(const ExceptLess&) /* noexcept */\n+  { }\n+\n+  bool\n+  operator()(int l, int r) const\n+  { return l < r; }\n+};\n+\n+typedef std::map<int, int, ExceptLess> emtype;\n+\n+static_assert( !noexcept( emtype(std::declval<emtype>(),\n+\t\tstd::declval<const typename emtype::allocator_type&>()) ),\n+\t       \"except move constructor with allocator\" );\ndiff --git a/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_move_construct.cc\nindex 03ef459..9acfbb5 100644\n--- a/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_move_construct.cc\n+++ b/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_move_construct.cc\n@@ -23,4 +23,25 @@\n \n typedef std::multimap<int, int> mmtype;\n \n-static_assert(std::is_nothrow_move_constructible<mmtype>::value, \"Error\");\n+static_assert( std::is_nothrow_move_constructible<mmtype>::value,\n+\t       \"noexcept move constructor\" );\n+static_assert( noexcept( mmtype(std::declval<mmtype>(),\n+\t\tstd::declval<const typename mmtype::allocator_type&>()) ),\n+\t       \"noexcept move constructor with allocator\" );\n+\n+struct ExceptLess\n+{\n+  ExceptLess() = default;\n+  ExceptLess(const ExceptLess&) /* noexcept */\n+  { }\n+\n+  bool\n+  operator()(int l, int r) const\n+  { return l < r; }\n+};\n+\n+typedef std::multimap<int, int, ExceptLess> emmtype;\n+\n+static_assert( !noexcept( emmtype(std::declval<emmtype>(),\n+\t\tstd::declval<const typename emmtype::allocator_type&>()) ),\n+\t       \"except move constructor with allocator\" );\ndiff --git a/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_move_construct.cc\nindex 49878e0..adc7a72 100644\n--- a/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_move_construct.cc\n+++ b/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_move_construct.cc\n@@ -23,4 +23,25 @@\n \n typedef std::multiset<int> mstype;\n \n-static_assert(std::is_nothrow_move_constructible<mstype>::value, \"Error\");\n+static_assert( std::is_nothrow_move_constructible<mstype>::value,\n+\t       \"noexcept move constructor\" );\n+static_assert( noexcept( mstype(std::declval<mstype>(),\n+\t\tstd::declval<const typename mstype::allocator_type&>()) ),\n+\t       \"noexcept move constructor with allocator\" );\n+\n+struct ExceptLess\n+{\n+  ExceptLess() = default;\n+  ExceptLess(const ExceptLess&) /* noexcept */\n+  { }\n+\n+  bool\n+  operator()(int l, int r) const\n+  { return l < r; }\n+};\n+\n+typedef std::multiset<int, ExceptLess> emstype;\n+\n+static_assert( !noexcept( emstype(std::declval<emstype>(),\n+\t\tstd::declval<const typename emstype::allocator_type&>()) ),\n+\t       \"except move constructor with allocator\" );\ndiff --git a/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_move_construct.cc\nindex 95b5100..0e1f2fa 100644\n--- a/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_move_construct.cc\n+++ b/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_move_construct.cc\n@@ -23,4 +23,25 @@\n \n typedef std::set<int> stype;\n \n-static_assert(std::is_nothrow_move_constructible<stype>::value, \"Error\");\n+static_assert( std::is_nothrow_move_constructible<stype>::value,\n+\t       \"noexcept move constructor\" );\n+static_assert( noexcept( stype(std::declval<stype>(),\n+\t\tstd::declval<const typename stype::allocator_type&>()) ),\n+\t       \"noexcept move constructor with allocator\" );\n+\n+struct ExceptLess\n+{\n+  ExceptLess() = default;\n+  ExceptLess(const ExceptLess&) /* noexcept */\n+  { }\n+\n+  bool\n+  operator()(int l, int r) const\n+  { return l < r; }\n+};\n+\n+typedef std::set<int, ExceptLess> estype;\n+\n+static_assert( !noexcept( estype(std::declval<estype>(),\n+\t\tstd::declval<const typename estype::allocator_type&>()) ),\n+\t       \"except move constructor with allocator\" );","headers":{"Return-Path":"<gcc-patches-return-462174-incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list gcc-patches@gcc.gnu.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=gcc-patches-return-462174-incoming=patchwork.ozlabs.org@gcc.gnu.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (1024-bit key;\n\tunprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org\n\theader.b=\"BUlEI8/Z\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xtTyZ518Pz9s82\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri, 15 Sep 2017 06:04:37 +1000 (AEST)","(qmail 49060 invoked by alias); 14 Sep 2017 20:04:28 -0000","(qmail 49040 invoked by uid 89); 14 Sep 2017 20:04:28 -0000","from mail-wr0-f172.google.com (HELO mail-wr0-f172.google.com)\n\t(209.85.128.172) by sourceware.org\n\t(qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP;\n\tThu, 14 Sep 2017 20:04:25 +0000","by mail-wr0-f172.google.com with SMTP id 108so302106wra.5;\n\tThu, 14 Sep 2017 13:04:25 -0700 (PDT)","from [192.168.0.23] (arf62-1-82-237-250-248.fbx.proxad.net.\n\t[82.237.250.248]) by smtp.googlemail.com with ESMTPSA id\n\t10sm11774827wrt.59.2017.09.14.13.04.20 (version=TLS1_2\n\tcipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tThu, 14 Sep 2017 13:04:21 -0700 (PDT)"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender:from\n\t:subject:to:cc:references:message-id:date:mime-version\n\t:in-reply-to:content-type; q=dns; s=default; b=JTl+1c8VqTLIt4YGW\n\tFAVz5ZCoAxrC5cSFvYbBViN9kk6gyiR8+JlBW6Bq3eBN2H1FTojKpVV6n3h8m2WB\n\taYqvEtnWPcDOCVhN5+CPyMN5QJEQl18jnB5MLiXouYBe+5CB1iOpJ7prVyZgBDlc\n\tqZ3dJUMatPDCWHXYC/LkuJDszY=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender:from\n\t:subject:to:cc:references:message-id:date:mime-version\n\t:in-reply-to:content-type; s=default; bh=lbs83A/YCD/QBTk+33qi82p\n\tGAjs=; b=BUlEI8/Zz5xDr0kHTBEYcPFrNkeI2cRWW9p1gz4cvug7aR2www3xM7M\n\tJnf/uqwRPry60r1cMPT28wwvg1jzywI27HZtIkguMYGReaMNZhGnLQyRLZXjo5Nh\n\tPAd5Pv0R8f3KCzC6JbNt7t33sISaZhYOMIiQ77bl3hnoDXslv8ms=","Mailing-List":"contact gcc-patches-help@gcc.gnu.org; run by ezmlm","Precedence":"bulk","List-Id":"<gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<mailto:gcc-patches-unsubscribe-incoming=patchwork.ozlabs.org@gcc.gnu.org>","List-Archive":"<http://gcc.gnu.org/ml/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-help@gcc.gnu.org>","Sender":"gcc-patches-owner@gcc.gnu.org","X-Virus-Found":"No","X-Spam-SWARE-Status":"No, score=-25.0 required=5.0 tests=AWL, BAYES_00,\n\tFREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2,\n\tGIT_PATCH_3, RCVD_IN_DNSWL_NONE,\n\tSPF_PASS autolearn=ham version=3.3.2 spammy=","X-Spam-User":"qpsmtpd, 2 recipients","X-HELO":"mail-wr0-f172.google.com","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net;\n\ts=20161025;\n\th=x-gm-message-state:from:subject:to:cc:references:message-id:date\n\t:user-agent:mime-version:in-reply-to:content-language;\n\tbh=pM64KoxNajMCavSksjz6qBom8gP/Apfmx63ppE434lQ=;\n\tb=lEzag9IoE4Tfl6ADdHJbxj2Lzi/9U5pQR+lDDK300STCnmzjWSPC8Tlunorb00CdCO\n\tFe6n+LM9MemzT0ffGkNxrwQYdfmqQ1Gdk9e4Y5dsJIV5T1H8f778o/7gyCxF+V7LvTUy\n\tgRtmuwKapOMA8e7cHj89fcx3P6ZgKfssjJj7n6dP7ry1jkTxbNiyCVbFWVIz0B5U5/Zn\n\tgDieNPKqjypfDyIfnf5eQbgaTFl2rUMSYyvVnQv84YhLrO12ASpD9rk4l3HYA11CeS9f\n\tMsUJ/NbDlxuuxylaBeiciw03zvD6r6KFZiZnnx4jkr6jAOMo7grsYCQ9bus/s8puLIGP\n\tt96A==","X-Gm-Message-State":"AHPjjUichs5OtyjWVxk+XWbhDwMXb14eCSDQlWbK3KrTcUVHHSoQ5DCz\thgBvhsbHj/NRm3rL","X-Google-Smtp-Source":"ADKCNb7pVx/38LxRfT+xILl4s12zkN/tDmoN5Sgb+oFtk6KYUIRKLfBae/J74iBmWqzKKAx2denMKQ==","X-Received":"by 10.223.138.151 with SMTP id\n\ty23mr17705690wry.244.1505419463242;\n\tThu, 14 Sep 2017 13:04:23 -0700 (PDT)","From":"=?utf-8?q?Fran=C3=A7ois_Dumont?= <frs.dumont@gmail.com>","Subject":"Re: Rb_tree constructor optimization","To":"Jonathan Wakely <jwakely@redhat.com>","Cc":"\"libstdc++@gcc.gnu.org\" <libstdc++@gcc.gnu.org>,\n\tgcc-patches <gcc-patches@gcc.gnu.org>","References":"<4026eacd-cb49-e756-c855-627cd5a40206@gmail.com>\n\t<20170908155011.GE4582@redhat.com>\n\t<f17199f2-c565-c8aa-e24b-10843785cf55@gmail.com>","Message-ID":"<5f54e6fb-0394-d13b-0e62-617cf0a2dbed@gmail.com>","Date":"Thu, 14 Sep 2017 22:04:19 +0200","User-Agent":"Mozilla/5.0 (X11; Linux x86_64;\n\trv:52.0) Gecko/20100101 Thunderbird/52.2.1","MIME-Version":"1.0","In-Reply-To":"<f17199f2-c565-c8aa-e24b-10843785cf55@gmail.com>","Content-Type":"multipart/mixed;\n\tboundary=\"------------9FA33ED09CB18A3BAE62A40D\""}},{"id":1790130,"web_url":"http://patchwork.ozlabs.org/comment/1790130/","msgid":"<501d0d42-07b2-d8ce-01a0-0dc29ddc3fed@gmail.com>","list_archive_url":null,"date":"2017-10-19T05:39:46","subject":"Re: Rb_tree constructor optimization","submitter":{"id":9231,"url":"http://patchwork.ozlabs.org/api/people/9231/","name":"François Dumont","email":"frs.dumont@gmail.com"},"content":"Hi\n\n     Any feedback regarding this patch ?\n\nThanks,\nFrançois\n\nOn 14/09/2017 22:04, François Dumont wrote:\n> I realized there was no test on the noexcept qualification of the move \n> constructor with allocator.\n>\n> I added some and found out that patch was missing a noexcept \n> qualification at _Rb_tree level.\n>\n> Here is the updated patch fully tested, ok to commit ?\n>\n> François\n>\n>\n> On 13/09/2017 21:57, François Dumont wrote:\n>> On 08/09/2017 17:50, Jonathan Wakely wrote:\n>>>\n>>> Since we know __a == __x.get_allocator() we could just do:\n>>>\n>>>      _Rb_tree(_Rb_tree&& __x, _Node_allocator&&, true_type)\n>>> noexcept(is_nothrow_move_constructible<_Rb_tree_impl<_Compare>>::value)\n>>>      : _M_impl(std::move(__x._M_impl))\n>>>      { }\n>>>\n>>> This means we don't need the new constructor.\n>>\n>>     You want to consider that a always equal allocator is stateless \n>> and so that the provided allocator rvalue reference do not need to be \n>> moved. IMHO you can have allocator with state that do not participate \n>> in comparison like some monitoring info.\n>>\n>>     I'm not confortable with that and prefer to keep current behavior \n>> so I propose this new patch considering all your other remarks.\n>>\n>>     I change noexcept qualification on [multi]map/set constructors to \n>> just rely on _Rep_type constructor noexcept qualification to not \n>> duplicate it.\n>>\n>> François\n>>\n>>\n>\n>\n>\ndiff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h\nindex bad6020..e343f04 100644\n--- a/libstdc++-v3/include/bits/stl_map.h\n+++ b/libstdc++-v3/include/bits/stl_map.h\n@@ -235,8 +235,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \n       /// Allocator-extended move constructor.\n       map(map&& __m, const allocator_type& __a)\n-      noexcept(is_nothrow_copy_constructible<_Compare>::value\n-\t       && _Alloc_traits::_S_always_equal())\n+      noexcept( noexcept(\n+\t_Rep_type(declval<_Rep_type>(), declval<_Pair_alloc_type>())) )\n       : _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { }\n \n       /// Allocator-extended initialier-list constructor.\ndiff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h\nindex 6f5cb7a..8c7ae2c 100644\n--- a/libstdc++-v3/include/bits/stl_multimap.h\n+++ b/libstdc++-v3/include/bits/stl_multimap.h\n@@ -232,8 +232,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \n       /// Allocator-extended move constructor.\n       multimap(multimap&& __m, const allocator_type& __a)\n-      noexcept(is_nothrow_copy_constructible<_Compare>::value\n-\t       && _Alloc_traits::_S_always_equal())\n+      noexcept( noexcept(\n+\t_Rep_type(declval<_Rep_type>(), declval<_Pair_alloc_type>())) )\n       : _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { }\n \n       /// Allocator-extended initialier-list constructor.\ndiff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h\nindex 517e77e..9ab4ab7 100644\n--- a/libstdc++-v3/include/bits/stl_multiset.h\n+++ b/libstdc++-v3/include/bits/stl_multiset.h\n@@ -244,8 +244,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \n       /// Allocator-extended move constructor.\n       multiset(multiset&& __m, const allocator_type& __a)\n-      noexcept(is_nothrow_copy_constructible<_Compare>::value\n-\t       && _Alloc_traits::_S_always_equal())\n+      noexcept( noexcept(\n+\t_Rep_type(declval<_Rep_type>(), declval<_Key_alloc_type>())) )\n       : _M_t(std::move(__m._M_t), _Key_alloc_type(__a)) { }\n \n       /// Allocator-extended initialier-list constructor.\ndiff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h\nindex e804a7c..6b64bcd 100644\n--- a/libstdc++-v3/include/bits/stl_set.h\n+++ b/libstdc++-v3/include/bits/stl_set.h\n@@ -248,8 +248,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \n       /// Allocator-extended move constructor.\n       set(set&& __x, const allocator_type& __a)\n-      noexcept(is_nothrow_copy_constructible<_Compare>::value\n-\t       && _Alloc_traits::_S_always_equal())\n+      noexcept( noexcept(\n+\t_Rep_type(declval<_Rep_type>(), declval<_Key_alloc_type>())) )\n       : _M_t(std::move(__x._M_t), _Key_alloc_type(__a)) { }\n \n       /// Allocator-extended initialier-list constructor.\ndiff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h\nindex c2417f1..ebfc3f9 100644\n--- a/libstdc++-v3/include/bits/stl_tree.h\n+++ b/libstdc++-v3/include/bits/stl_tree.h\n@@ -704,6 +704,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n #else\n \t  _Rb_tree_impl(_Rb_tree_impl&&) = default;\n \n+\t  _Rb_tree_impl(_Rb_tree_impl&& __x, _Node_allocator&& __a)\n+\t  : _Node_allocator(std::move(__a)),\n+\t    _Base_key_compare(std::move(__x)),\n+\t    _Rb_tree_header(std::move(__x))\n+\t  { }\n+\n \t  _Rb_tree_impl(const _Key_compare& __comp, _Node_allocator&& __a)\n \t  : _Node_allocator(std::move(__a)), _Base_key_compare(__comp)\n \t  { }\n@@ -944,10 +950,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n       _Rb_tree(_Rb_tree&&) = default;\n \n       _Rb_tree(_Rb_tree&& __x, const allocator_type& __a)\n+      noexcept( noexcept(\n+\t_Rb_tree(declval<_Rb_tree>(), declval<_Node_allocator>())) )\n       : _Rb_tree(std::move(__x), _Node_allocator(__a))\n       { }\n \n-      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a);\n+    private:\n+      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, true_type)\n+      noexcept(is_nothrow_move_constructible<_Rb_tree_impl<_Compare>>::value)\n+      : _M_impl(std::move(__x._M_impl), std::move(__a))\n+      { }\n+\n+      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, false_type)\n+      : _M_impl(__x._M_impl._M_key_compare, std::move(__a))\n+      {\n+\tif (__x._M_root() != nullptr)\n+\t  _M_move_data(__x, false_type{});\n+      }\n+\n+    public:\n+      _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a)\n+      noexcept( noexcept(\n+\t_Rb_tree(declval<_Rb_tree>(), declval<_Node_allocator>(),\n+\t\t declval<typename _Alloc_traits::is_always_equal>()) ) )\n+      : _Rb_tree(std::move(__x), std::move(__a),\n+\t\t typename _Alloc_traits::is_always_equal{})\n+      { }\n #endif\n \n       ~_Rb_tree() _GLIBCXX_NOEXCEPT\n@@ -1347,22 +1375,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n     private:\n       // Move elements from container with equal allocator.\n       void\n-      _M_move_data(_Rb_tree& __x, std::true_type)\n+      _M_move_data(_Rb_tree& __x, true_type)\n       { _M_impl._M_move_data(__x._M_impl); }\n \n       // Move elements from container with possibly non-equal allocator,\n       // which might result in a copy not a move.\n       void\n-      _M_move_data(_Rb_tree&, std::false_type);\n+      _M_move_data(_Rb_tree&, false_type);\n \n       // Move assignment from container with equal allocator.\n       void\n-      _M_move_assign(_Rb_tree&, std::true_type);\n+      _M_move_assign(_Rb_tree&, true_type);\n \n       // Move assignment from container with possibly non-equal allocator,\n       // which might result in a copy not a move.\n       void\n-      _M_move_assign(_Rb_tree&, std::false_type);\n+      _M_move_assign(_Rb_tree&, false_type);\n #endif\n \n #if __cplusplus > 201402L\n@@ -1590,23 +1618,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n #if __cplusplus >= 201103L\n   template<typename _Key, typename _Val, typename _KeyOfValue,\n \t   typename _Compare, typename _Alloc>\n-    _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::\n-    _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a)\n-    : _M_impl(__x._M_impl._M_key_compare, std::move(__a))\n-    {\n-      using __eq = typename _Alloc_traits::is_always_equal;\n-      if (__x._M_root() != nullptr)\n-\t_M_move_data(__x, __eq());\n-    }\n-\n-  template<typename _Key, typename _Val, typename _KeyOfValue,\n-\t   typename _Compare, typename _Alloc>\n     void\n     _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::\n-    _M_move_data(_Rb_tree& __x, std::false_type)\n+    _M_move_data(_Rb_tree& __x, false_type)\n     {\n       if (_M_get_Node_allocator() == __x._M_get_Node_allocator())\n-\t_M_move_data(__x, std::true_type());\n+\t_M_move_data(__x, true_type());\n       else\n \t{\n \t  _Alloc_node __an(*this);\n@@ -1628,7 +1645,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n     {\n       clear();\n       if (__x._M_root() != nullptr)\n-\t_M_move_data(__x, std::true_type());\n+\t_M_move_data(__x, true_type());\n       std::__alloc_on_move(_M_get_Node_allocator(),\n \t\t\t   __x._M_get_Node_allocator());\n     }\ndiff --git a/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_move_construct.cc\nindex b172df7..97c1a47 100644\n--- a/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_move_construct.cc\n+++ b/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_move_construct.cc\n@@ -23,4 +23,25 @@\n \n typedef std::map<int, int> mtype;\n \n-static_assert(std::is_nothrow_move_constructible<mtype>::value, \"Error\");\n+static_assert( std::is_nothrow_move_constructible<mtype>::value,\n+\t       \"noexcept move constructor\" );\n+static_assert( noexcept( mtype(std::declval<mtype>(),\n+\t\tstd::declval<const typename mtype::allocator_type&>()) ),\n+\t       \"noexcept move constructor with allocator\" );\n+\n+struct ExceptLess\n+{\n+  ExceptLess() = default;\n+  ExceptLess(const ExceptLess&) /* noexcept */\n+  { }\n+\n+  bool\n+  operator()(int l, int r) const\n+  { return l < r; }\n+};\n+\n+typedef std::map<int, int, ExceptLess> emtype;\n+\n+static_assert( !noexcept( emtype(std::declval<emtype>(),\n+\t\tstd::declval<const typename emtype::allocator_type&>()) ),\n+\t       \"except move constructor with allocator\" );\ndiff --git a/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_move_construct.cc\nindex 03ef459..9acfbb5 100644\n--- a/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_move_construct.cc\n+++ b/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_move_construct.cc\n@@ -23,4 +23,25 @@\n \n typedef std::multimap<int, int> mmtype;\n \n-static_assert(std::is_nothrow_move_constructible<mmtype>::value, \"Error\");\n+static_assert( std::is_nothrow_move_constructible<mmtype>::value,\n+\t       \"noexcept move constructor\" );\n+static_assert( noexcept( mmtype(std::declval<mmtype>(),\n+\t\tstd::declval<const typename mmtype::allocator_type&>()) ),\n+\t       \"noexcept move constructor with allocator\" );\n+\n+struct ExceptLess\n+{\n+  ExceptLess() = default;\n+  ExceptLess(const ExceptLess&) /* noexcept */\n+  { }\n+\n+  bool\n+  operator()(int l, int r) const\n+  { return l < r; }\n+};\n+\n+typedef std::multimap<int, int, ExceptLess> emmtype;\n+\n+static_assert( !noexcept( emmtype(std::declval<emmtype>(),\n+\t\tstd::declval<const typename emmtype::allocator_type&>()) ),\n+\t       \"except move constructor with allocator\" );\ndiff --git a/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_move_construct.cc\nindex 49878e0..adc7a72 100644\n--- a/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_move_construct.cc\n+++ b/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_move_construct.cc\n@@ -23,4 +23,25 @@\n \n typedef std::multiset<int> mstype;\n \n-static_assert(std::is_nothrow_move_constructible<mstype>::value, \"Error\");\n+static_assert( std::is_nothrow_move_constructible<mstype>::value,\n+\t       \"noexcept move constructor\" );\n+static_assert( noexcept( mstype(std::declval<mstype>(),\n+\t\tstd::declval<const typename mstype::allocator_type&>()) ),\n+\t       \"noexcept move constructor with allocator\" );\n+\n+struct ExceptLess\n+{\n+  ExceptLess() = default;\n+  ExceptLess(const ExceptLess&) /* noexcept */\n+  { }\n+\n+  bool\n+  operator()(int l, int r) const\n+  { return l < r; }\n+};\n+\n+typedef std::multiset<int, ExceptLess> emstype;\n+\n+static_assert( !noexcept( emstype(std::declval<emstype>(),\n+\t\tstd::declval<const typename emstype::allocator_type&>()) ),\n+\t       \"except move constructor with allocator\" );\ndiff --git a/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_move_construct.cc\nindex 95b5100..0e1f2fa 100644\n--- a/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_move_construct.cc\n+++ b/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_move_construct.cc\n@@ -23,4 +23,25 @@\n \n typedef std::set<int> stype;\n \n-static_assert(std::is_nothrow_move_constructible<stype>::value, \"Error\");\n+static_assert( std::is_nothrow_move_constructible<stype>::value,\n+\t       \"noexcept move constructor\" );\n+static_assert( noexcept( stype(std::declval<stype>(),\n+\t\tstd::declval<const typename stype::allocator_type&>()) ),\n+\t       \"noexcept move constructor with allocator\" );\n+\n+struct ExceptLess\n+{\n+  ExceptLess() = default;\n+  ExceptLess(const ExceptLess&) /* noexcept */\n+  { }\n+\n+  bool\n+  operator()(int l, int r) const\n+  { return l < r; }\n+};\n+\n+typedef std::set<int, ExceptLess> estype;\n+\n+static_assert( !noexcept( estype(std::declval<estype>(),\n+\t\tstd::declval<const typename estype::allocator_type&>()) ),\n+\t       \"except move constructor with allocator\" );","headers":{"Return-Path":"<gcc-patches-return-464490-incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list gcc-patches@gcc.gnu.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=gcc-patches-return-464490-incoming=patchwork.ozlabs.org@gcc.gnu.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (1024-bit key;\n\tunprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org\n\theader.b=\"afxM4MN4\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3yHd721FFbz9t4P\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 19 Oct 2017 16:40:10 +1100 (AEDT)","(qmail 35039 invoked by alias); 19 Oct 2017 05:39:55 -0000","(qmail 35011 invoked by uid 89); 19 Oct 2017 05:39:54 -0000","from mail-wm0-f42.google.com (HELO mail-wm0-f42.google.com)\n\t(74.125.82.42) by sourceware.org\n\t(qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP;\n\tThu, 19 Oct 2017 05:39:51 +0000","by mail-wm0-f42.google.com with SMTP id f4so13911035wme.0;\n\tWed, 18 Oct 2017 22:39:51 -0700 (PDT)","from [10.24.8.66] ([109.190.253.11]) by smtp.googlemail.com with\n\tESMTPSA id d49sm9703567edb.79.2017.10.18.22.39.47\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256\n\tbits=128/128); Wed, 18 Oct 2017 22:39:48 -0700 (PDT)"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender\n\t:subject:from:to:cc:references:message-id:date:mime-version\n\t:in-reply-to:content-type; q=dns; s=default; b=u0RO2vPXxSnyWOyWM\n\tIXAA713sTz8cOXF2w7E3OOukCii3popZnlxvLknwRvUMP81wFtDVHFmQ+sxQ8IQC\n\tCN598Fd0dXfufrL7dz/870S5uWSS0TICcJceB6g3uhnq9bZ8TrTinHsaSiBLgqpU\n\tjqEeUJJYrEG6xc2MjAO0YQXogw=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender\n\t:subject:from:to:cc:references:message-id:date:mime-version\n\t:in-reply-to:content-type; s=default; bh=lrv7vKTuadrjqcL9VYBgdSd\n\tRe1Y=; b=afxM4MN47BKEMJwyjjP4sneFfR/JVIgUcoMAo0SDjAoxS9VuHPND1Sv\n\t3K0qPzt/uUj+i6CFf0tNIlFUQA77I1OovO3qdewk6bzVKUm+F+izxloGkpw0aqOn\n\twDihZdl+Narpl8FVtwZIvv91PtWVC8IsZUOo+6fih0nkY0Cqzt3A=","Mailing-List":"contact gcc-patches-help@gcc.gnu.org; run by ezmlm","Precedence":"bulk","List-Id":"<gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<mailto:gcc-patches-unsubscribe-incoming=patchwork.ozlabs.org@gcc.gnu.org>","List-Archive":"<http://gcc.gnu.org/ml/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-help@gcc.gnu.org>","Sender":"gcc-patches-owner@gcc.gnu.org","X-Virus-Found":"No","X-Spam-SWARE-Status":"No, score=-26.9 required=5.0 tests=BAYES_00,\n\tFREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2,\n\tGIT_PATCH_3, RCVD_IN_DNSWL_NONE,\n\tSPF_PASS autolearn=ham version=3.3.2 spammy=16457","X-Spam-User":"qpsmtpd, 2 recipients","X-HELO":"mail-wm0-f42.google.com","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net;\n\ts=20161025;\n\th=x-gm-message-state:subject:from:to:cc:references:message-id:date\n\t:user-agent:mime-version:in-reply-to:content-language;\n\tbh=ZvbrMcP+Ud+jDhkSa2XG7nhHUXuVb/cGDjhxtQYFak4=;\n\tb=ItMDxFmAM6XRgZ6ulLmMjl9Oa27/y0tDP1jLaa7Vsub3/vpMM1wSYJDQqWlkgJvboH\n\ty0PRW9Xef/FevlPH9ePxSe9fPfOzrVthEQztS7HcsQCeEQTUtwjh19RPEOZdN7UQH22b\n\tXHg83EtC2/bjyztGD7I2KIfM0HRXDl/XnET5XOTLX9Vc6aKRQ7ufOMrJeCMy4WEIFLSv\n\td3SjPtOaNP7xT+dcEHdZFimcHniRbhQw2IrlT7p1PKftMV4vpPJiMjBMysTQldJZdbys\n\tDgWkQNrCJ7hZLUSMsJIdmc0D1bkB5LM4TRvHDpaHPFQFKfVFwrN6iO9Tq7RcIjruPice\n\tq48A==","X-Gm-Message-State":"AMCzsaWp7P/G1dwS47B30bqWdrCctP7tzx2bw9H9OxK770A0tHsUfzLg\t+GbX0iLst/V7qf6Od6I3rGeOHQ==","X-Google-Smtp-Source":"ABhQp+QaE3dn6y4Y3WoC6IeanNTyx90MmTxbduh2nZknd7TlKbPHv4ese6bmx3Of2nc/ykPGafKX+Q==","X-Received":"by 10.80.195.74 with SMTP id q10mr984329edb.144.1508391589200;\n\tWed, 18 Oct 2017 22:39:49 -0700 (PDT)","Subject":"Re: Rb_tree constructor optimization","From":"=?utf-8?q?Fran=C3=A7ois_Dumont?= <frs.dumont@gmail.com>","To":"Jonathan Wakely <jwakely@redhat.com>","Cc":"\"libstdc++@gcc.gnu.org\" <libstdc++@gcc.gnu.org>,\n\tgcc-patches <gcc-patches@gcc.gnu.org>","References":"<4026eacd-cb49-e756-c855-627cd5a40206@gmail.com>\n\t<20170908155011.GE4582@redhat.com>\n\t<f17199f2-c565-c8aa-e24b-10843785cf55@gmail.com>\n\t<5f54e6fb-0394-d13b-0e62-617cf0a2dbed@gmail.com>","Message-ID":"<501d0d42-07b2-d8ce-01a0-0dc29ddc3fed@gmail.com>","Date":"Thu, 19 Oct 2017 07:39:46 +0200","User-Agent":"Mozilla/5.0 (X11; Linux x86_64;\n\trv:52.0) Gecko/20100101 Thunderbird/52.3.0","MIME-Version":"1.0","In-Reply-To":"<5f54e6fb-0394-d13b-0e62-617cf0a2dbed@gmail.com>","Content-Type":"multipart/mixed;\n\tboundary=\"------------84444AA808AA295D98197CA1\""}}]