220 37005 <CAC+0CCP2ns-7-kaAU8p6w1MkuZPL-7rXo7AudccEWf=oX--n1g@mail.gmail.com> article
Path: news.gmane.org!.POSTED!not-for-mail
From: Jake Arkinstall <jake.arkinstall@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: pseudo constness
Date: Thu, 22 Feb 2018 20:50:38 +0000
Lines: 677
Approved: news@gmane.org
Message-ID: <CAC+0CCP2ns-7-kaAU8p6w1MkuZPL-7rXo7AudccEWf=oX--n1g@mail.gmail.com>
References: <f202be10-efb5-4f1a-ab6a-18bf6ac873ee@isocpp.org>
 <CAC+0CCPGJ2J=y3x-2voHCffyXTqsPVwWyyjR99v6R-XgyU1V4w@mail.gmail.com>
 <CAC+0CCPu0dEAb9B=KmpiT8NwYd4xgSBuUWYcTRrui_Xj5K+WFA@mail.gmail.com>
 <CAC+0CCNyfhb7L2dk4N0pyu3d=T7q1L5m+nOU2yG05XXj4dH_vg@mail.gmail.com>
 <1519283315.58210.23.camel@gmail.com> <CAC+0CCNYk37F3bivpoKcLLUvEwi+sJAn2O_DF9cP7ZfjBSjHVg@mail.gmail.com>
 <CAC4OUEa2Zk9Wv4YtqbT0w-sUhMqF2mZu36QhQW7e=r-X2+asjQ@mail.gmail.com>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary="001a114b171c38fb1f0565d332ef"
X-Trace: blaine.gmane.org 1519332519 28867 195.159.176.226 (22 Feb 2018 20:48:39 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Thu, 22 Feb 2018 20:48:39 +0000 (UTC)
To: std-proposals@isocpp.org
Original-X-From: std-proposals+bncBDCZX3WUUQFRBH62XTKAKGQECH3EVYI@isocpp.org Thu Feb 22 21:48:35 2018
Return-path: <std-proposals+bncBDCZX3WUUQFRBH62XTKAKGQECH3EVYI@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-vk0-f72.google.com ([209.85.213.72])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBDCZX3WUUQFRBH62XTKAKGQECH3EVYI@isocpp.org>)
	id 1eoxn9-00074Q-0z
	for gclcip-std-proposals@m.gmane.org; Thu, 22 Feb 2018 21:48:35 +0100
Original-Received: by mail-vk0-f72.google.com with SMTP id y144sf3473554vky.14
        for <gclcip-std-proposals@m.gmane.org>; Thu, 22 Feb 2018 12:50:41 -0800 (PST)
ARC-Seal: i=2; a=rsa-sha256; t=1519332641; cv=pass;
        d=google.com; s=arc-20160816;
        b=LJT63OGkf28ZLlPERKZoLTnnYIV2PTxreY8HLdgjpAhAuY2KnKdGnVrDqNlHQffVkG
         TkexVK6Fw/Ff8p6A44tac7mSG0DvaWi7j8qRlPdosfDuhLmnz6ORuEspEGTidxsaT2lL
         Qi5cNrpFuskGJT03wCpx/rNJRD8vx5ylIxVVC6x3bAjyrVo8P3XCfOC0usSpyZNf0D2u
         qvZPp06uXCvAkTjjinjQB5GVIQsZL86/qxfetjdTvmS442RAoQqEV6UQnd7s+SHYbIXt
         SKVkwjs48MnUx2pRHpYm6XWa2PIDzZd4FmVgRVMo/LsRsl3VHPMET1uxMFc/iRaVLdwh
         RyCg==
ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
        h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post
         :list-id:mailing-list:precedence:reply-to:to:subject:message-id:date
         :from:references:in-reply-to:mime-version:arc-authentication-results
         :arc-message-signature:dkim-signature:arc-authentication-results;
        bh=u+nR8I1haZQVTIe27V0D4Ns5dC/iEwQSHoyBys5KcLc=;
        b=z+Dte/dzRzW5Px+9mn/ZofI+Xpax7NcziqzJnJ9pJ8WMqg/YIQkCnu0wPsBBbwEMal
         LDsWQi4fN87jHXZld3ButYbgY5yakiIGGnhtSZ4Int+L0Aw5F88dVE1SPqyvHtZRjZbu
         RExxLPM/75TWHZrTz4hq+VraprXhhAW4loJAtEcCz42qExlATurxIfK7lJLBTMnSgFxH
         1IYQddtO0thegmcqLUMDk8UIsgjxK/vVZaZiCcxMRqa+uTjKnYyQIjU5wYBoElGXHcV1
         JnibNRyjD3DM75SOP82uuRgQx9NWNG9N5vO65L/rta//3YwHbWRGgnknh6xyYsMDiStd
         vGSA==
ARC-Authentication-Results: i=2; mx.google.com;
       dkim=pass header.i=@gmail.com header.s=20161025 header.b=eE0CNohk;
       spf=pass (google.com: domain of jake.arkinstall@gmail.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=jake.arkinstall@gmail.com;
       dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=mime-version:in-reply-to:references:from:date:message-id:subject:to
         :x-original-sender:x-original-authentication-results:reply-to
         :precedence:mailing-list:list-id:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=u+nR8I1haZQVTIe27V0D4Ns5dC/iEwQSHoyBys5KcLc=;
        b=sQnrJn6t6GC5vZyzIcYrbQyecCoGnomZk6/vegDTW18wQusu7/pz5n5/6PSQXDfi8r
         JXa5oeaFecnn5/3J8U5HJmm5SA6vDmLogAHsEWjOCAotieKwROLi4sWB6i+Tzr0r+Y8o
         ksm782IkPOTXIHhFGKArN9XEhrBfNc+ZWTyuNioeuf8VTJyRqvo6SDrxmlVJ68mulpiu
         ROSpkcSX+sQP3Tz+SIBw2fVCZ2NiPdTyhOOSZIoNZCqKQm06Tm6PB2imyoIbJZCoZMIm
         Bece2AwmDEGQyMdD5l5jUHht5n3nMn4kR3EgpejVStoITlfBAQE7oRcOF8F0LlrCLgAr
         y8bw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:mime-version:in-reply-to:references:from:date
         :message-id:subject:to:x-original-sender
         :x-original-authentication-results:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=u+nR8I1haZQVTIe27V0D4Ns5dC/iEwQSHoyBys5KcLc=;
        b=W4IdnEh8KI6DnCL/GB/xNS1E8KceeGcq/HB1Xu8S7od4zm7r44iH30IctEsThXt4PR
         OD5BCg+IVeVoNQQcOJSxqL+LC2aVeMFzIPH0Eq2G9nnH/ZhEwqlSh2AMGbNQGpNDbvhm
         BbfrOydbGr/syN/BWBUguHon3IRf8zHHPpv7txENv4ji20VMQ34O5Oy3R/FIa2DYYnD1
         hLSBEgfHZ4zopxElbqmgxNj/FonqzO1npKsAjExmNtNzmQlwL5zvFxdQxprinYxEmji4
         gWD1hN/L8DRyo6NgMXBo+MLXQPPKroWGerK42XmAfPDi7ZoxXhvPgHAaG+JfJH48wYsJ
         ZSZg==
X-Gm-Message-State: APf1xPC3FGsVj4MSeJvPjPFJi7mgRsHMGJy0hU5OUBc0ikSCdO6DPZFx
	18DRxjx4lFvRaakiSgV4jC5r2w==
X-Google-Smtp-Source: AH8x226nstdRiT9+bipdgT3wlGYqwZzVDKkqrHLFDsFYzJrCYkbSV480RyCAwgokYeaixs2aNiXZhQ==
X-Received: by 10.31.146.140 with SMTP id u134mr4204020vkd.9.1519332641294;
        Thu, 22 Feb 2018 12:50:41 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.31.70.1 with SMTP id t1ls2460626vka.19.gmail; Thu, 22 Feb 2018
 12:50:39 -0800 (PST)
X-Received: by 10.31.63.6 with SMTP id m6mr6575166vka.43.1519332639471;
        Thu, 22 Feb 2018 12:50:39 -0800 (PST)
ARC-Seal: i=1; a=rsa-sha256; t=1519332639; cv=none;
        d=google.com; s=arc-20160816;
        b=urg18SZ93h1limgfVpQCDX8VqopKAZTfEK1nVcXEdgGIJuhAG4x6NSBqioqkPmlsgR
         Wgf3L3A/qLBAMmh4tppSLz0rDV4NXygwUfCnK6WdBkulDnhzHfn0ibPCsnoWfxEHXl2z
         FhceiXpfRaWYnHrLUfjFGAkaORo7+KAKV6blnXEoXfgxrwppetsliALANB1kjb4GIWIT
         lKWt2fNESDQA0CfJjVc49UPg9tZ7rFZbZSM1IVMk0RatAcBBmEQNPuaW5Gzn1NxeMEhq
         JtMpsExrKfwuCMzUmz75ZfG4st0IRPK/PFV5UTiIyrXw+ZVs51Bqqf9/UOnWl9w1CeCh
         94NA==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
        h=to:subject:message-id:date:from:references:in-reply-to:mime-version
         :dkim-signature:arc-authentication-results;
        bh=skN7muiDBgF7os3P/lAev8AwGkYoJQiph/KBhuezf2w=;
        b=tFCU6kBnN7OV5hTSNo43A6OQbnspUx4pNIWEvtXCLTv+JuMEJkDq4+XcRG5EHO/xCV
         UNqBYwTYNqE+jZNpq8b8PcRMKKNVqA8W61ru7UFjsjwPsWYtFMZj/r7rwG/fXiN3JLAr
         eOFIgX7PrpiVr4RY+7WnDUR9uS/ROfc6UL9UvWt+b929LD8KX3bPFZHchH9HLFOq998L
         4Vq7K828sLvjJmIcuECCdnDqab3hfUHowk75z9PpsDeZGD+cG0qm7z3+FD6oplyC4RQs
         Zu/jjDFNZTMc1hFjB/fY4NzF2me5KXX9ryJGomGPDQAYoDXiJvnpZuzcB0nyYE6f0Zxi
         3rGw==
ARC-Authentication-Results: i=1; mx.google.com;
       dkim=pass header.i=@gmail.com header.s=20161025 header.b=eE0CNohk;
       spf=pass (google.com: domain of jake.arkinstall@gmail.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=jake.arkinstall@gmail.com;
       dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com
Original-Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65])
        by mx.google.com with SMTPS id y37sor411776uah.0.2018.02.22.12.50.39
        for <std-proposals@isocpp.org>
        (Google Transport Security);
        Thu, 22 Feb 2018 12:50:39 -0800 (PST)
Received-SPF: pass (google.com: domain of jake.arkinstall@gmail.com designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65;
X-Received: by 10.159.41.33 with SMTP id t30mr6361842uat.16.1519332638651;
 Thu, 22 Feb 2018 12:50:38 -0800 (PST)
Original-Received: by 10.176.4.16 with HTTP; Thu, 22 Feb 2018 12:50:38 -0800 (PST)
Original-Received: by 10.176.4.16 with HTTP; Thu, 22 Feb 2018 12:50:38 -0800 (PST)
In-Reply-To: <CAC4OUEa2Zk9Wv4YtqbT0w-sUhMqF2mZu36QhQW7e=r-X2+asjQ@mail.gmail.com>
X-Original-Sender: jake.arkinstall@gmail.com
X-Original-Authentication-Results: mx.google.com;       dkim=pass
 header.i=@gmail.com header.s=20161025 header.b=eE0CNohk;       spf=pass
 (google.com: domain of jake.arkinstall@gmail.com designates 209.85.220.65 as
 permitted sender) smtp.mailfrom=jake.arkinstall@gmail.com;       dmarc=pass
 (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Spam-Checked-In-Group: std-proposals@isocpp.org
X-Google-Group-Id: 399137483710
List-Post: <https://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <https://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <https://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:37005
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/37005>

--001a114b171c38fb1f0565d332ef
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

But again, the two main issues are that it is not const during the duration
of the method, and the compiler will not be able to determine if the final
call truly is the reverse of A.

Perhaps if there were a way of creating a reversible operation in a
self-contained manner, I'd be more confident. An example of this would be a
library that allows one to define an algorithm in such a manner as the
compiler is able to reverse it (with certain assumptions about various
undefined behaviours, maybe; remember that incrementing signed integer
types beyond their max, or decrementing them from zero, is undefined
behaviour and as such may not be valid on all systems).

I would take great interest, albeit academic, in this kind of approach. It
would likely need a list of reversible instructions, for which the reverse
can be determined (without necessarily relying on operator- being the
reverse of operator+, because that is user defined for custom classes and
they have every possibility of not being opposites). The list is iterated
forwards with the initial operations, then iterated backwards with the
reverse operations, to undo it.

Without such an approach, we lose all confidence in pseudo-constness from
the POV of the compiler. I still don't see what benefit pseudo-const would
provide, though. There is no optimisation benefit, and its use in a
threaded application is limited.

Note also that the same effect is possible by creating a view on the class,
allowing you to be const without copying anything.

On 22 Feb 2018 20:30, "J=C3=A9r=C3=B4me Saint-Martin" <jsaintmartin356@gmai=
l.com>
wrote:

> A pseudo const method is a method who calls a method A at its beginning,
> few const methods, and then the reverse method A
>
> On Thu, Feb 22, 2018 at 2:44 PM, Jake Arkinstall <
> jake.arkinstall@gmail.com> wrote:
>
>> It's better to have the method as non-const and deal with the
>> consequences, if possible, than to make a vital class data member mutabl=
e.
>> The former does not trick the user into creating unwanted side-effects, =
but
>> the latter can. The former is honest, the latter is a trickster.
>>
>> There's certainly a place for mutable, but not here IMO.
>>
>>
>> On 22 Feb 2018 07:08, "Richard Hodges" <hodges.r@gmail.com> wrote:
>>
>> On Thu, 2018-02-22 at 01:13 +0000, Jake Arkinstall wrote:
>> > Further to my previous reply, I have written a rough version which
>> > should be a bit more reliable (it isn't perfect, but should suffice
>> > for the purpose of demonstration).
>>
>>
>> C++ already provides the mutable keyword. The Vec class in question can
>> be written in terms of it:
>>
>> class Vec {
>> public :
>>     Vec () : val_ (std::vector<size_t> (1000, 0)) {}
>>
>>     // copy constructor is un-necessary. The compiler builds a correct
>>     // one.
>>
>>     //actual const method
>>     void next2() const {
>>         inc ();
>>         dec ();
>>     }
>>
>>     // these are now const
>>     void inc () const {
>>         std::for_each (val_.begin (), val_.end (),
>>                        [] (size_t&s) {++s;});
>>     }
>>
>>     void dec () const {
>>         std::for_each (val_.begin (), val_.end (),
>>                        [] (size_t&s) {--s;});
>>     }
>>
>> private :
>>     // mutable members can be modified when the object is accessed
>>     // through a const reference
>>     mutable std::vector<size_t> val_;
>> };
>>
>>
>>
>>
>> >
>> > Inserting to std::cout (especially with a flush, i.e. as std::endl)
>> > can play hell during the benchmark stage, so I have removed that. I
>> > have also ensured that each benchmark minimally interferes with the
>> > others (by scoping each out), extracted the time for the copying
>> > operation (as it isn't valid to compare Vec::Vec() and Vec::Vec(const
>> > Vec&) - the two do different things). Most importantly, the methods
>> > are run many times to minimise statistical error and to try and iron
>> > out the impact of e.g. dynamic frequency scaling.
>> >
>> > > #include <vector>
>> > > #include <iostream>
>> > > #include <algorithm>
>> > > #include <functional>
>> > >
>> > >
>> > > class Vec {
>> > > public :
>> > >     Vec () : val_ (std::vector<size_t> (1000, 0)) {}
>> > >     Vec (const Vec& v) : val_ (v.val_) {}
>> > >     //couple of const opposite methods
>> > >     void inc () {
>> > >         std::for_each (val_.begin (), val_.end (), [] (size_t&s)
>> > > {++s;});
>> > >     }
>> > >     void dec () {
>> > >         std::for_each (val_.begin (), val_.end (), [] (size_t&s) {-
>> > > -s;});
>> > >     }
>> > >     void next2const () const {
>> > >         Vec v (*this);
>> > >         v.inc();
>> > >         v.dec();
>> > >     }
>> > >     void next2pseudoconst() { //pseudo const method
>> > >         inc ();
>> > >         dec ();
>> > >     }
>> > > private :
>> > >     std::vector<size_t> val_;
>> > > };
>> > >
>> > > template<typename T>
>> > > void crude_bench(T func, const size_t& count){
>> > >     clock_t t =3D clock();
>> > >     for(size_t i =3D 0; i < count; ++i){
>> > >         func();
>> > >     }
>> > >     double duration{(clock() - t) / (double)count};
>> > >     std::cout << duration << " ticks per run\n";
>> > > }
>> > >
>> > > int main (int argc, char* argv []) {
>> > >     auto count =3D 100000ul;
>> > >     {
>> > >         Vec v;
>> > >         std::cout << "Copying: " << std::flush;
>> > >         crude_bench(
>> > >             std::bind([](Vec& v){ Vec other(v); }, v),
>> > >             count
>> > >         );
>> > >     }
>> > >     {
>> > >         Vec v;
>> > >         std::cout << "next2const: " << std::flush;
>> > >         crude_bench(
>> > >             std::bind(&Vec::next2const, v),
>> > >             count
>> > >         );
>> > >     }
>> > >     {
>> > >         Vec v;
>> > >         std::cout << "next2pseudoconst: " << std::flush;
>> > >         crude_bench(
>> > >             std::bind(&Vec::next2pseudoconst, v),
>> > >             count
>> > >         );
>> > >     }
>> > >     return 0;
>> > > }
>> > >
>> >
>> > Without any optimisation on GCC, what I get is:
>> >
>> > > Copying: 0.31656 ticks per run
>> > > next2const: 18.2984 ticks per run
>> > > next2pseudoconst: 18.0145 ticks per run
>> >
>> > Note that the next2const duration minus the Copying duration (which
>> > is necessary to compare the two) is less than the next2pseudoconst
>> > duration - but not by any meaningful amount. There's a good reason
>> > for that - const doesn't perform any kind of magic here. It wouldn't
>> > make sense if it did, although the Vec method is const, it still
>> > creates another Vec and performs a non-const operation upon THAT.
>> >
>> > Just as a sidenote as to the importance of running benchmarks over
>> > many iterations. I have run the above benchmark over iterations
>> > increasing in powers of 2, and charted the ticks per iteration for
>> > GCC7.3.1 unoptimised and GCC7.3.1 with -O3. I'm not sure if I can
>> > attach the charts to the group via email attachment, so I have
>> > uploaded them here: https://imgur.com/a/Mj2P6 - the two lines
>> > correspond with ticks(next2pseudoconst) and ticks(next2const)-
>> > ticks(copying) - You can see the negative tick count of (next2const -
>> > copying) in the first iteration, which should go some way to tell you
>> > how unreliable a single run benchmark is.
>> >
>> > Regards,
>> > Jake Arkinstall
>> >
>> > On Wed, Feb 21, 2018 at 11:35 PM, Jake Arkinstall <jake.arkinstall@gm
>> > ail.com> wrote:
>> > > Also note that you're including the allocation of 1000 size_ts in
>> > > that first timer. I'm not at my PC right now to test, but does
>> > > moving the initialization of V to before the clock start
>> > > significantly reduce the discrepancy?
>> > >
>> > > On 21 Feb 2018 23:23, "Jake Arkinstall" <jake.arkinstall@gmail.com>
>> > > wrote:
>> > > > Welcome!
>> > > >
>> > > > Perhaps you can explain the consequences further, namely give an
>> > > > example of something useful that it would allow.
>> > > >
>> > > > One of the benefits of having something const is not just that
>> > > > the data is unchanged at the END, but that it doesn't change AT
>> > > > ALL during execution. This is often useful in a threaded
>> > > > situation (when you want to make sure you don't introduce race
>> > > > conditions), and its primary purpose is to stop you from making
>> > > > mistakes rather than to optimise.
>> > > >
>> > > > On top of this, the compiler is able to easily determine whether
>> > > > or not you are obeying the const declaration in the definition of
>> > > > a method, in that only const operations are used inside of it -
>> > > > how is the compiler supposed to verify if the second method
>> > > > actually reverses the first? Trust the developer? Because that's
>> > > > the situation we have without const already.
>> > > >
>> > > > On 21 Feb 2018 23:00, <jsaintmartin356@gmail.com> wrote:
>> > > > > One of my post on stackoverflow.com was said to have its place
>> > > > > here.
>> > > > >
>> > > > > https://stackoverflow.com/questions/48915277/what-about-pseudoc
>> > > > > onst-qualifier
>> > > > >
>> > > > > What do you think about my new pseudoconst qualifier ?
>> > > > > Expecting for your answer, (and/or possibly a job: long
>> > > > > unemployed at the moment)
>> > > > >
>> > > > > Jerome Saint-Martin,
>> > > > > Montrouge, France
>> > > > >
>> > > > >
>> > > > >
>>
>> --
>> You received this message because you are subscribed to the Google Group=
s
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send a=
n
>> email to std-proposals+unsubscribe@isocpp.org.
>> To post to this group, send email to std-proposals@isocpp.org.
>> To view this discussion on the web visit https://groups.google.com/a/is
>> ocpp.org/d/msgid/std-proposals/1519283315.58210.23.camel%40gmail.com.
>>
>>
>> --
>> You received this message because you are subscribed to the Google Group=
s
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send a=
n
>> email to std-proposals+unsubscribe@isocpp.org.
>> To post to this group, send email to std-proposals@isocpp.org.
>> To view this discussion on the web visit https://groups.google.com/a/is
>> ocpp.org/d/msgid/std-proposals/CAC%2B0CCNYk37F3bivpoKcLLUvEw
>> i%2BsJAn2O_DF9cP7ZfjBSjHVg%40mail.gmail.com
>> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAC%2B0CCN=
Yk37F3bivpoKcLLUvEwi%2BsJAn2O_DF9cP7ZfjBSjHVg%40mail.gmail.com?utm_medium=
=3Demail&utm_source=3Dfooter>
>> .
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit https://groups.google.com/a/
> isocpp.org/d/msgid/std-proposals/CAC4OUEa2Zk9Wv4YtqbT0w-
> sUhMqF2mZu36QhQW7e%3Dr-X2%2BasjQ%40mail.gmail.com
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAC4OUEa2Zk=
9Wv4YtqbT0w-sUhMqF2mZu36QhQW7e%3Dr-X2%2BasjQ%40mail.gmail.com?utm_medium=3D=
email&utm_source=3Dfooter>
> .
>

--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CAC%2B0CCP2ns-7-kaAU8p6w1MkuZPL-7rXo7AudccEWf%3D=
oX--n1g%40mail.gmail.com.

--001a114b171c38fb1f0565d332ef
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"auto">But again, the two main issues are that it is not const d=
uring the duration of the method, and the compiler will not be able to dete=
rmine if the final call truly is the reverse of A.<div dir=3D"auto"><br></d=
iv><div dir=3D"auto">Perhaps if there were a way of creating a reversible o=
peration in a self-contained manner, I&#39;d be more confident. An example =
of this would be a library that allows one to define an algorithm in such a=
 manner as the compiler is able to reverse it (with certain assumptions abo=
ut various undefined behaviours, maybe; remember that incrementing signed i=
nteger types beyond their max, or decrementing them from zero, is undefined=
 behaviour and as such may not be valid on all systems).<div dir=3D"auto"><=
br></div><div dir=3D"auto">I would take great interest, albeit academic, in=
 this kind of approach. It would likely need a list of reversible instructi=
ons, for which the reverse can be determined (without necessarily relying o=
n operator- being the reverse of operator+, because that is user defined fo=
r custom classes and they have every possibility of not being opposites). T=
he list is iterated forwards with the initial operations, then iterated bac=
kwards with the reverse operations, to undo it.</div><div dir=3D"auto"><br>=
</div><div dir=3D"auto">Without such an approach, we lose all confidence in=
 pseudo-constness from the POV of the compiler. I still don&#39;t see what =
benefit pseudo-const would provide, though. There is no optimisation benefi=
t, and its use in a threaded application is limited.</div><div dir=3D"auto"=
><br></div><div dir=3D"auto">Note also that the same effect is possible by =
creating a view on the class, allowing you to be const without copying anyt=
hing.</div></div></div><div class=3D"gmail_extra"><br><div class=3D"gmail_q=
uote">On 22 Feb 2018 20:30, &quot;J=C3=A9r=C3=B4me Saint-Martin&quot; &lt;<=
a href=3D"mailto:jsaintmartin356@gmail.com">jsaintmartin356@gmail.com</a>&g=
t; wrote:<br type=3D"attribution"><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr">A pseudo const method is a method who calls a method A at its begi=
nning, few const methods, and then the reverse method A<br></div><div class=
=3D"gmail_extra"><br><div class=3D"gmail_quote">On Thu, Feb 22, 2018 at 2:4=
4 PM, Jake Arkinstall <span dir=3D"ltr">&lt;<a href=3D"mailto:jake.arkinsta=
ll@gmail.com" target=3D"_blank">jake.arkinstall@gmail.com</a>&gt;</span> wr=
ote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border=
-left:1px #ccc solid;padding-left:1ex"><div dir=3D"auto"><div>It&#39;s bett=
er to have the method as non-const and deal with the consequences, if possi=
ble, than to make a vital class data member mutable. The former does not tr=
ick the user into creating unwanted side-effects, but the latter can. The f=
ormer is honest, the latter is a trickster.<div dir=3D"auto"><br></div><div=
 dir=3D"auto">There&#39;s certainly a place for mutable, but not here IMO.<=
/div><div><div class=3D"m_-1486869905183559635h5"><br><div class=3D"gmail_e=
xtra"><br><div class=3D"gmail_quote">On 22 Feb 2018 07:08, &quot;Richard Ho=
dges&quot; &lt;<a href=3D"mailto:hodges.r@gmail.com" target=3D"_blank">hodg=
es.r@gmail.com</a>&gt; wrote:<br type=3D"attribution"><blockquote class=3D"=
m_-1486869905183559635m_-6116896630151128286quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div class=3D"m_-1486869905=
183559635m_-6116896630151128286quoted-text">On Thu, 2018-02-22 at 01:13 +00=
00, Jake Arkinstall wrote:<br>
&gt; Further to my previous reply, I have written a rough version which<br>
&gt; should be a bit more reliable (it isn&#39;t perfect, but should suffic=
e<br>
&gt; for the purpose of demonstration).<br>
<br>
<br>
</div>C++ already provides the mutable keyword. The Vec class in question c=
an<br>
be written in terms of it:<br>
<div class=3D"m_-1486869905183559635m_-6116896630151128286quoted-text"><br>
class Vec {<br>
public :<br>
=C2=A0 =C2=A0 Vec () : val_ (std::vector&lt;size_t&gt; (1000, 0)) {}<br>
<br>
</div>=C2=A0 =C2=A0 // copy constructor is un-necessary. The compiler build=
s a correct<br>
=C2=A0 =C2=A0 // one.<br>
<br>
=C2=A0 =C2=A0 //actual const method<br>
=C2=A0 =C2=A0 void next2() const {<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 inc ();<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 dec ();<br>
=C2=A0 =C2=A0 }<br>
<br>
=C2=A0 =C2=A0 // these are now const<br>
=C2=A0 =C2=A0 void inc () const {<br>
<div class=3D"m_-1486869905183559635m_-6116896630151128286quoted-text">=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 std::for_each (val_.begin (), val_.end (),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0[] (size_t&amp;s) {++s;});<br>
=C2=A0 =C2=A0 }<br>
<br>
</div>=C2=A0 =C2=A0 void dec () const {<br>
<div class=3D"m_-1486869905183559635m_-6116896630151128286quoted-text">=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 std::for_each (val_.begin (), val_.end (),<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0[] (size_t&amp;s) {--s;});<br>
=C2=A0 =C2=A0 }<br>
<br>
</div>private :<br>
=C2=A0 =C2=A0 // mutable members can be modified when the object is accesse=
d<br>
=C2=A0 =C2=A0 // through a const reference<br>
=C2=A0 =C2=A0 mutable std::vector&lt;size_t&gt; val_;<br>
};<br>
<div class=3D"m_-1486869905183559635m_-6116896630151128286elided-text"><br>
<br>
<br>
<br>
&gt;<br>
&gt; Inserting to std::cout (especially with a flush, i.e. as std::endl)<br=
>
&gt; can play hell during the benchmark stage, so I have removed that. I<br=
>
&gt; have also ensured that each benchmark minimally interferes with the<br=
>
&gt; others (by scoping each out), extracted the time for the copying<br>
&gt; operation (as it isn&#39;t valid to compare Vec::Vec() and Vec::Vec(co=
nst<br>
&gt; Vec&amp;) - the two do different things). Most importantly, the method=
s<br>
&gt; are run many times to minimise statistical error and to try and iron<b=
r>
&gt; out the impact of e.g. dynamic frequency scaling.<br>
&gt;<br>
&gt; &gt; #include &lt;vector&gt;<br>
&gt; &gt; #include &lt;iostream&gt;<br>
&gt; &gt; #include &lt;algorithm&gt;<br>
&gt; &gt; #include &lt;functional&gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; class Vec {<br>
&gt; &gt; public :<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0Vec () : val_ (std::vector&lt;size_t&gt; (1000=
, 0)) {}<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0Vec (const Vec&amp; v) : val_ (v.val_) {}<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0//couple of const opposite methods<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0void inc () {<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std::for_each (val_.begin (), va=
l_.end (), [] (size_t&amp;s)<br>
&gt; &gt; {++s;});<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0}<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0void dec () {<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std::for_each (val_.begin (), va=
l_.end (), [] (size_t&amp;s) {-<br>
&gt; &gt; -s;});<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0}<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0void next2const () const {<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Vec v (*this);<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0v.inc();<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0v.dec();<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0}<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0void next2pseudoconst() { //pseudo const metho=
d<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0inc ();<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dec ();<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0}<br>
&gt; &gt; private :<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0std::vector&lt;size_t&gt; val_;<br>
&gt; &gt; };<br>
&gt; &gt;<br>
&gt; &gt; template&lt;typename T&gt;<br>
&gt; &gt; void crude_bench(T func, const size_t&amp; count){<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0clock_t t =3D clock();<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0for(size_t i =3D 0; i &lt; count; ++i){<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0func();<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0}<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0double duration{(clock() - t) / (double)count}=
;<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0std::cout &lt;&lt; duration &lt;&lt; &quot; ti=
cks per run\n&quot;;<br>
&gt; &gt; }<br>
&gt; &gt;<br>
&gt; &gt; int main (int argc, char* argv []) {<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0auto count =3D 100000ul;<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0{<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Vec v;<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std::cout &lt;&lt; &quot;Copying=
: &quot; &lt;&lt; std::flush;<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0crude_bench(<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std::bind([](Vec&a=
mp; v){ Vec other(v); }, v),<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0count<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0}<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0{<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Vec v;<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std::cout &lt;&lt; &quot;next2co=
nst: &quot; &lt;&lt; std::flush;<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0crude_bench(<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std::bind(&amp;Vec=
::next2const, v),<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0count<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0}<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0{<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Vec v;<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std::cout &lt;&lt; &quot;next2ps=
eudoconst: &quot; &lt;&lt; std::flush;<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0crude_bench(<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std::bind(&amp;Vec=
::next2pseudoco<wbr>nst, v),<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0count<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0}<br>
&gt; &gt;=C2=A0 =C2=A0 =C2=A0return 0;<br>
&gt; &gt; }<br>
&gt; &gt;<br>
&gt;<br>
&gt; Without any optimisation on GCC, what I get is:<br>
&gt;<br>
&gt; &gt; Copying: 0.31656 ticks per run<br>
&gt; &gt; next2const: 18.2984 ticks per run<br>
&gt; &gt; next2pseudoconst: 18.0145 ticks per run<br>
&gt;<br>
&gt; Note that the next2const duration minus the Copying duration (which<br=
>
&gt; is necessary to compare the two) is less than the next2pseudoconst<br>
&gt; duration - but not by any meaningful amount. There&#39;s a good reason=
<br>
&gt; for that - const doesn&#39;t perform any kind of magic here. It wouldn=
&#39;t<br>
&gt; make sense if it did, although the Vec method is const, it still<br>
&gt; creates another Vec and performs a non-const operation upon THAT.<br>
&gt;<br>
&gt; Just as a sidenote as to the importance of running benchmarks over<br>
&gt; many iterations. I have run the above benchmark over iterations<br>
&gt; increasing in powers of 2, and charted the ticks per iteration for<br>
&gt; GCC7.3.1 unoptimised and GCC7.3.1 with -O3. I&#39;m not sure if I can<=
br>
&gt; attach the charts to the group via email attachment, so I have<br>
&gt; uploaded them here: <a href=3D"https://imgur.com/a/Mj2P6" rel=3D"noref=
errer" target=3D"_blank">https://imgur.com/a/Mj2P6</a> - the two lines<br>
&gt; correspond with ticks(next2pseudoconst) and ticks(next2const)-<br>
&gt; ticks(copying) - You can see the negative tick count of (next2const -<=
br>
&gt; copying) in the first iteration, which should go some way to tell you<=
br>
&gt; how unreliable a single run benchmark is.<br>
&gt;<br>
&gt; Regards,<br>
&gt; Jake Arkinstall<br>
&gt;<br>
&gt; On Wed, Feb 21, 2018 at 11:35 PM, Jake Arkinstall &lt;jake.arkinstall@=
gm<br>
&gt; <a href=3D"http://ail.com" rel=3D"noreferrer" target=3D"_blank">ail.co=
m</a>&gt; wrote:<br>
&gt; &gt; Also note that you&#39;re including the allocation of 1000 size_t=
s in<br>
&gt; &gt; that first timer. I&#39;m not at my PC right now to test, but doe=
s<br>
&gt; &gt; moving the initialization of V to before the clock start<br>
&gt; &gt; significantly reduce the discrepancy?<br>
&gt; &gt;<br>
&gt; &gt; On 21 Feb 2018 23:23, &quot;Jake Arkinstall&quot; &lt;<a href=3D"=
mailto:jake.arkinstall@gmail.com" target=3D"_blank">jake.arkinstall@gmail.c=
om</a>&gt;<br>
&gt; &gt; wrote:<br>
&gt; &gt; &gt; Welcome!<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; Perhaps you can explain the consequences further, namely giv=
e an<br>
&gt; &gt; &gt; example of something useful that it would allow.<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; One of the benefits of having something const is not just th=
at<br>
&gt; &gt; &gt; the data is unchanged at the END, but that it doesn&#39;t ch=
ange AT<br>
&gt; &gt; &gt; ALL during execution. This is often useful in a threaded<br>
&gt; &gt; &gt; situation (when you want to make sure you don&#39;t introduc=
e race<br>
&gt; &gt; &gt; conditions), and its primary purpose is to stop you from mak=
ing<br>
&gt; &gt; &gt; mistakes rather than to optimise.<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; On top of this, the compiler is able to easily determine whe=
ther<br>
&gt; &gt; &gt; or not you are obeying the const declaration in the definiti=
on of<br>
&gt; &gt; &gt; a method, in that only const operations are used inside of i=
t -<br>
&gt; &gt; &gt; how is the compiler supposed to verify if the second method<=
br>
&gt; &gt; &gt; actually reverses the first? Trust the developer? Because th=
at&#39;s<br>
&gt; &gt; &gt; the situation we have without const already.<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; On 21 Feb 2018 23:00, &lt;<a href=3D"mailto:jsaintmartin356@=
gmail.com" target=3D"_blank">jsaintmartin356@gmail.com</a>&gt; wrote:<br>
&gt; &gt; &gt; &gt; One of my post on <a href=3D"http://stackoverflow.com" =
rel=3D"noreferrer" target=3D"_blank">stackoverflow.com</a> was said to have=
 its place<br>
&gt; &gt; &gt; &gt; here.<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; <a href=3D"https://stackoverflow.com/questions/48915277=
/what-about-pseudoc" rel=3D"noreferrer" target=3D"_blank">https://stackover=
flow.com/ques<wbr>tions/48915277/what-about-pseu<wbr>doc</a><br>
&gt; &gt; &gt; &gt; onst-qualifier<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; What do you think about my new pseudoconst qualifier ?<=
br>
&gt; &gt; &gt; &gt; Expecting for your answer, (and/or possibly a job: long=
<br>
&gt; &gt; &gt; &gt; unemployed at the moment)<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; Jerome Saint-Martin,<br>
&gt; &gt; &gt; &gt; Montrouge, France<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;<br>
<br>
--<br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@isoc<wbr>pp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
</div>To view this discussion on the web visit <a href=3D"https://groups.go=
ogle.com/a/isocpp.org/d/msgid/std-proposals/1519283315.58210.23.camel%40gma=
il.com" rel=3D"noreferrer" target=3D"_blank">https://groups.google.com/a/is=
<wbr>ocpp.org/d/msgid/std-proposals<wbr>/1519283315.58210.23.camel%40g<wbr>=
mail.com</a>.<br>
</blockquote></div><br></div></div></div></div></div><div><div class=3D"m_-=
1486869905183559635h5">

<p></p>

-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@isoc<wbr>pp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br></div></div>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAC%2B0CCNYk37F3bivpoKcLLUvEwi%2BsJAn=
2O_DF9cP7ZfjBSjHVg%40mail.gmail.com?utm_medium=3Demail&amp;utm_source=3Dfoo=
ter" target=3D"_blank">https://groups.google.com/a/is<wbr>ocpp.org/d/msgid/=
std-proposals<wbr>/CAC%2B0CCNYk37F3bivpoKcLLUvEw<wbr>i%2BsJAn2O_DF9cP7ZfjBS=
jHVg%40m<wbr>ail.gmail.com</a>.<br>
</blockquote></div><br></div>

<p></p>

-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAC4OUEa2Zk9Wv4YtqbT0w-sUhMqF2mZu36Qh=
QW7e%3Dr-X2%2BasjQ%40mail.gmail.com?utm_medium=3Demail&amp;utm_source=3Dfoo=
ter" target=3D"_blank">https://groups.google.com/a/<wbr>isocpp.org/d/msgid/=
std-<wbr>proposals/<wbr>CAC4OUEa2Zk9Wv4YtqbT0w-<wbr>sUhMqF2mZu36QhQW7e%3Dr-=
X2%<wbr>2BasjQ%40mail.gmail.com</a>.<br>
</blockquote></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAC%2B0CCP2ns-7-kaAU8p6w1MkuZPL-7rXo7=
AudccEWf%3DoX--n1g%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAC%2B0CCP2ns=
-7-kaAU8p6w1MkuZPL-7rXo7AudccEWf%3DoX--n1g%40mail.gmail.com</a>.<br />

--001a114b171c38fb1f0565d332ef--

.
