220 18358 <556E3353.10809@gmail.com> article
Path: news.gmane.org!not-for-mail
From: Miro Knejp <miro.knejp@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Re: Core Language feature: Multiple assignments
 from multiple return values via tuple
Date: Wed, 03 Jun 2015 00:50:59 +0200
Lines: 767
Approved: news@gmane.org
Message-ID: <556E3353.10809@gmail.com>
References: <69a59613-6504-466a-9878-786653d6087f@isocpp.org> <0b91248a-1994-4127-932e-9e1d97edadb2@isocpp.org> <ae452ecd-fcf2-49c5-8df8-e15687ebbbe0@isocpp.org> <62FE5462-BE3F-4C9E-B03D-322CB0CFF753@gmail.com> <22a4d6a5-f6f1-4ed1-9ec9-743c32173f81@isocpp.org> <67f765e2-8b7e-4a78-a548-643b691d0a72@isocpp.org> <1335ae00-da12-4aca-864d-e4380018c692@isocpp.org> <48761b84-6677-44c1-8651-544df59c5a4e@isocpp.org> <mk5a73$mor$1@ger.gmane.org> <8  56bf86a-b1f3-49ea-887e-67f5815f43c9@isocpp.org> <mk7ert$94r$1@ger.gmane.org> <515eedbd-7268-4871-bb66-426ab16524d3@isocpp.org> <mk80ui$sqv$1@ger.gmane.org> <83820b3d-1f8b-4f00-b8ed-f35d3391622f@isocpp.org> <mk9vss$va7$1@ger.gmane.org> <938268b7-e8eb-424b-8874-dfc6e543dc13@isocpp.org> <mkcorf$dsn$1@ger.gmane.org> <9852296b-e143-49ee-bde5-5a72c838cb40@isoc
 pp.org> <mki2ih$uh4$1@ger.gmane.org> <11ebcee2-3a73-462d-99be-609273339a92@isocpp.org> <6F892DDD-D1C2-446F-84E6-A2B81D096B2B@gmail.com> <9f3a42b5-befc-42e9-b739-654675eb4e02@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative;
 boundary="------------020902030005000301030404"
X-Trace: ger.gmane.org 1433285543 13085 80.91.229.3 (2 Jun 2015 22:52:23 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Tue, 2 Jun 2015 22:52:23 +0000 (UTC)
To: std-proposals@isocpp.org
Original-X-From: std-proposals+bncBC6ONSXJ54LBBOXGXCVQKGQEGWEJL2A@isocpp.org Wed Jun 03 00:52:16 2015
Return-path: <std-proposals+bncBC6ONSXJ54LBBOXGXCVQKGQEGWEJL2A@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-wg0-f72.google.com ([74.125.82.72])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBC6ONSXJ54LBBOXGXCVQKGQEGWEJL2A@isocpp.org>)
	id 1Yzv12-0004yJ-7a
	for gclcip-std-proposals@m.gmane.org; Wed, 03 Jun 2015 00:50:36 +0200
Original-Received: by wgla2 with SMTP id a2sf44041142wgl.1
        for <gclcip-std-proposals@m.gmane.org>; Tue, 02 Jun 2015 15:50:35 -0700 (PDT)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-gm-message-state:message-id:date:from:user-agent:mime-version:to
         :subject:references:in-reply-to:content-type: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=Fpat3eggoLn1/hjJJu/Rb7Wwtb3bS+QaYMViypwqSno=;
        b=OVaArxg/kpaiDGMY03Ff2fis4q8PDSe9GzmFS9eBzuN0OEeSzey4fkugPKYd7yCNXU
         RfFnaswNzhsmCw/i76a/JsLPqOyWVrVefnNkDHrWb93+PKOrWdHpzsy9bBwyOnTp93Wq
         uqJX2gynYmuKX0s+rHmwmV44AvxTAMeNLFfKkorx/dSx0c8ozxZcvVRfuzCuxJAzhtLV
         m0U9gkGx8nxC6COXTjSkqn8dS62rlF5qBMMtTnFI9YLKftW6L4Kj3PdK1V42TVZkjZnz
         EQkgtrWCeH2TpI/yWPd+3ZLH2HTZsOfmHqgJttK4XCKCnbpr/OmPtrCSueMrKqSxA23u
         O5Nw==
X-Gm-Message-State: ALoCoQlDct5vOQb4yeIsX8nxqzn0voXqlGeV01lv1/KHPn2/SpNwFHudwag81fe8mzmRvWZnNxd3
X-Received: by 10.112.148.101 with SMTP id tr5mr28050837lbb.13.1433285435695;
        Tue, 02 Jun 2015 15:50:35 -0700 (PDT)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.180.109.230 with SMTP id hv6ls640227wib.28.canary; Tue, 02 Jun
 2015 15:50:34 -0700 (PDT)
X-Received: by 10.194.200.194 with SMTP id ju2mr53686305wjc.61.1433285434417;
        Tue, 02 Jun 2015 15:50:34 -0700 (PDT)
Original-Received: from mail-wi0-x229.google.com (mail-wi0-x229.google.com. [2a00:1450:400c:c05::229])
        by mx.google.com with ESMTPS id qr7si27152121wic.24.2015.06.02.15.50.34
        for <std-proposals@isocpp.org>
        (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
        Tue, 02 Jun 2015 15:50:34 -0700 (PDT)
Received-SPF: pass (google.com: domain of miro.knejp@gmail.com designates 2a00:1450:400c:c05::229 as permitted sender) client-ip=2a00:1450:400c:c05::229;
Original-Received: by wizo1 with SMTP id o1so1333861wiz.1
        for <std-proposals@isocpp.org>; Tue, 02 Jun 2015 15:50:34 -0700 (PDT)
X-Received: by 10.180.100.194 with SMTP id fa2mr35281537wib.8.1433285434004;
        Tue, 02 Jun 2015 15:50:34 -0700 (PDT)
Original-Received: from [192.168.42.33] (ppp-93-104-176-167.dynamic.mnet-online.de. [93.104.176.167])
        by mx.google.com with ESMTPSA id wr6sm3451954wjb.21.2015.06.02.15.50.32
        for <std-proposals@isocpp.org>
        (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
        Tue, 02 Jun 2015 15:50:33 -0700 (PDT)
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0
In-Reply-To: <9f3a42b5-befc-42e9-b739-654675eb4e02@isocpp.org>
X-Original-Sender: miro.knejp@gmail.com
X-Original-Authentication-Results: mx.google.com;       spf=pass (google.com:
 domain of miro.knejp@gmail.com designates 2a00:1450:400c:c05::229 as
 permitted sender) smtp.mail=miro.knejp@gmail.com;       dkim=pass
 header.i=@gmail.com;       dmarc=pass (p=NONE 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-Google-Group-Id: 399137483710
List-Post: <http://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <http://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <http://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <http://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>,
 <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:18358
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/18358>

This is a multi-part message in MIME format.
--------------020902030005000301030404
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable


Am 02.06.2015 um 20:46 schrieb Nicol Bolas:
>
>
> On Tuesday, June 2, 2015 at 8:17:53 AM UTC-4, Miro Knejp wrote:
>
>     I was thinking some more about how this could be implemented and
>     just wanted to give my viewpoint on this.
>
>     Disclaimer: In all examples below I assume the comma operator does
>     not exist and is more or less pseudocode to make it more readable.
>     Syntax bikeshedding can be done once the semantic issues are
>     solved. I also assume none of the functions are inlined.
>
>     Consider how RVO is typically done today. Given the function
>
>     T foo(A a, B b);
>
>     and assuming T is too big to be passed in registers. Now imagining
>     the function performs RVO the compiler transforms this signature
>     in something like
>
>     void foo(T* result, A a, B b);
>
>
> It would be better to say that the compiler turns it into:
>
> void foo(void *result, A a, B b);
Sheesh, you did get the point where I said it's pseudocode, right?
>
> I say that because it isn't a `T` yet; it's `foo` that initailizes the=20
> memory into a `T`. Also because:
>
>     Now imagine we have multiple return values:
>
>     T, U, V bar(A a, B b)
>
>     In the best-case scenario RVO is possible for all three return
>     values, transforming the function into
>
>     struct __Result { T t; U u; V v; };
>     void bar(__Result* result, A a, B b);
>
>
> Then you get to ignore the whole `__Result` thing. Consider a more=20
> complete version of both of these. If you have:
Uhm, no? Plenty of examples follow this where __Result is used. This=20
isn't helpful.
>
> |
> T t =3Dfoo(a,b);
>
> //Becomes:
>
> void*__temp =3D__alloc_from_stack(sizeof(T));
> foo(__temp,a,b);
> T &t =3D*(reinterpret_cast<T*>(__temp));
> |
>
> For the MRV case:
>
> |
> [T t,U u,V v]=3Dfoo(a,b);
>
> //Becomes:
>
> void*__temp=20
> =3D__alloc_from_stack(sizeof(T)+sizeof(U)+sizeof(V));//Ignoring obvious=
=20
> alignment issues here
> foo(__temp,a,b);//Foo knows how to offset into the temporary memory to=20
> store each return value.
> T &t =3D*(reinterpret_cast<T*>(__temp));
> U &u=20
> =3D*(reinterpret_cast<U*>(reinterpret_cast<char*>(__temp)+sizeof(T)));//A=
gain=20
> ignore alignment
> V &v=20
> =3D*(reinterpret_cast<V*>(reinterpret_cast<char*>(__temp)+sizeof(T)+sizeo=
f(U)));//Again=20
> ignore alignment
> |
>
And this is why I chose pseudocode.
> This way, we don't have to think in terms of explicit "structs"; it's=20
> all just memory and ABI layout.
>
>     This assumes all three types are copyable or at least movable to
>     their final destination.
>
>
> If you ever do `T t =3D foo();`, the compiler /requires/ that no there=20
> is an accessible copy/move constructor. The copy/move operation may be=20
> elided, but it still must be accessible.
>
>     In the case where all three return values are used for
>     initialization this is pretty trivial.
>
>     T t, U u, V v =3D bar(a, b);
>
>     transforms into
>
>     #1
>     __Result __result; // not initialized
>     bar(&__result, a, b);
>     // t, u, v are now aliases to __result.t, __result.u, __result.v
>
>     Now what if the initialization is different
>
>     #2
>     T t;
>     U u;
>     t, u, V v =3D bar(a, b);
>
>     This must be transformed to
>
>     __Result __result; // not initialized
>     bar(&__result, A a, B b);
>     // v is now an alias to result.v
>     t =3D std::move(__result.t);
>     u =3D std::move(__result.u);
>     __result.u.~U();
>     __result.t.~T();
>
>     This means there is wasted stack space for t and u (due to the
>     fixed layout of __Result) __result.t and __result.u have to stay
>     until v goes out of scope. It could be recycled for other
>     variables, but just saying.
>
>
> How is that any different from the single return value case, when you=20
> store the result into a live object? Of course you have to copy/move=20
> the result into it. Elision only when when you /initializing/ the=20
> return value.
>
> MRV doesn't change that in any way.
I didn't claim it changes anything. Here we only *initialize* one=20
object, the other two are temporaries assigned to live objects.
>
>     I guess my whole point here is that there are at least two ways to
>     implement this that need to be hammered into the ABI and dictate
>     how much flexibility the caller has and how much call overhead
>     there is per return value (1 or n additional pointers pushed).
>     Once there is a syntax for this compiler-generated unpacking it
>     can surely be extended to user-defined types. I just don=E2=80=99t th=
ink
>     that there is as much elision potential for user-defined types.
>
>
> Except that there's plenty of elision of potential for user-defined=20
> types. Indeed, modern C++ syntax is designed around the assumption=20
> that elision exists and will make code as fast as possible. Every time=20
> you see someone write `T t =3D stuff();` instead of an explicit=20
> `stuff(&t, );`, you are implicitly relying on elision to make this fast.
>
> Why should MRVs undo this syntactic progress?
They shouldn't! My whole point was that this is doable. In multiple=20
ways. With elision. Transparent to the language user for built-in MRVs.=20
In fact I'm supporting your side of the argument for not artificially=20
force std::tuple into it. Ugh.

--=20

---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

--------------020902030005000301030404
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<html>
  <head>
    <meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
  </head>
  <body bgcolor=3D"#FFFFFF" text=3D"#000000">
    <br>
    <div class=3D"moz-cite-prefix">Am 02.06.2015 um 20:46 schrieb Nicol
      Bolas:<br>
    </div>
    <blockquote
      cite=3D"mid:9f3a42b5-befc-42e9-b739-654675eb4e02@isocpp.org"
      type=3D"cite">
      <div dir=3D"ltr"><br>
        <br>
        On Tuesday, June 2, 2015 at 8:17:53 AM UTC-4, Miro Knejp wrote:
        <blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
          0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">I was
          thinking some more about how this could be implemented and
          just wanted to give my viewpoint on this.
          <br>
          <br>
          Disclaimer: In all examples below I assume the comma operator
          does not exist and is more or less pseudocode to make it more
          readable. Syntax bikeshedding can be done once the semantic
          issues are solved. I also assume none of the functions are
          inlined.
          <br>
          <br>
          Consider how RVO is typically done today. Given the function
          <br>
          <br>
          T foo(A a, B b);
          <br>
          <br>
          and assuming T is too big to be passed in registers. Now
          imagining the function performs RVO the compiler transforms
          this signature in something like
          <br>
          <br>
          void foo(T* result, A a, B b);<br>
        </blockquote>
        <div><br>
          It would be better to say that the compiler turns it into:<br>
          <br>
          void foo(void *result, A a, B b);<br>
        </div>
      </div>
    </blockquote>
    Sheesh, you did get the point where I said it's pseudocode, right?
    <blockquote
      cite=3D"mid:9f3a42b5-befc-42e9-b739-654675eb4e02@isocpp.org"
      type=3D"cite">
      <div dir=3D"ltr">
        <div><br>
          I say that because it isn't a `T` yet; it's `foo` that
          initailizes the memory into a `T`. Also because:<br>
          =C2=A0</div>
        <blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
          0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
          Now imagine we have multiple return values:
          <br>
          <br>
          T, U, V bar(A a, B b)
          <br>
          <br>
          In the best-case scenario RVO is possible for all three return
          values, transforming the function into
          <br>
          <br>
          struct __Result { T t; U u; V v; };
          <br>
          void bar(__Result* result, A a, B b);<br>
        </blockquote>
        <div><br>
          Then you get to ignore the whole `__Result` thing. Consider a
          more complete version of both of these. If you have:<br>
        </div>
      </div>
    </blockquote>
    Uhm, no? Plenty of examples follow this where __Result is used. This
    isn't helpful.
    <blockquote
      cite=3D"mid:9f3a42b5-befc-42e9-b739-654675eb4e02@isocpp.org"
      type=3D"cite">
      <div dir=3D"ltr">
        <div><br>
          <div class=3D"prettyprint" style=3D"background-color: rgb(250,
            250, 250); border-color: rgb(187, 187, 187); border-style:
            solid; border-width: 1px; word-wrap: break-word;"><code
              class=3D"prettyprint">
              <div class=3D"subprettyprint"><span style=3D"color: #000;"
                  class=3D"styled-by-prettify">T t </span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> foo<=
/span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">a</sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> b</s=
pan><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">);</s=
pan><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"><br>
                  <br>
                </span><span style=3D"color: #800;"
                  class=3D"styled-by-prettify">//Becomes:</span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"><br>
                  <br>
                </span><span style=3D"color: #008;"
                  class=3D"styled-by-prettify">void</span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">*</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">__tem=
p
                </span><span style=3D"color: #660;"
                  class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or:
                  #000;" class=3D"styled-by-prettify"> __alloc_from_stack</=
span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
                  style=3D"color: #008;" class=3D"styled-by-prettify">sizeo=
f</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">T</sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">));</=
span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"><br>
                  foo</span><span style=3D"color: #660;"
                  class=3D"styled-by-prettify">(</span><span style=3D"color=
:
                  #000;" class=3D"styled-by-prettify">__temp</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> a</s=
pan><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> b</s=
pan><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">);</s=
pan><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"><br>
                  T </span><span style=3D"color: #660;"
                  class=3D"styled-by-prettify">&amp;</span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">t </s=
pan><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">*(</s=
pan><span
                  style=3D"color: #008;" class=3D"styled-by-prettify">reint=
erpret_cast</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">&lt;<=
/span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">T</sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">*&gt;=
(</span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">__tem=
p</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">));</=
span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"><br>
                </span></div>
            </code></div>
          <br>
          For the MRV case:<br>
          <br>
          <div class=3D"prettyprint" style=3D"background-color: rgb(250,
            250, 250); border-color: rgb(187, 187, 187); border-style:
            solid; border-width: 1px; word-wrap: break-word;"><code
              class=3D"prettyprint">
              <div class=3D"subprettyprint"><span style=3D"color: #660;"
                  class=3D"styled-by-prettify">[</span><span style=3D"color=
:
                  #000;" class=3D"styled-by-prettify">T t</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> U u<=
/span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> V v<=
/span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">]</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> foo<=
/span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">a</sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> b</s=
pan><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">);</s=
pan><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"><br>
                  <br>
                </span><span style=3D"color: #800;"
                  class=3D"styled-by-prettify">//Becomes:</span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"><br>
                  <br>
                </span><span style=3D"color: #008;"
                  class=3D"styled-by-prettify">void</span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">*</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">__tem=
p
                </span><span style=3D"color: #660;"
                  class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or:
                  #000;" class=3D"styled-by-prettify"> __alloc_from_stack</=
span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
                  style=3D"color: #008;" class=3D"styled-by-prettify">sizeo=
f</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">T</sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">)</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">+</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #008;" class=3D"styled-by-prettify">sizeo=
f</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">U</sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">)</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">+</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #008;" class=3D"styled-by-prettify">sizeo=
f</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">V</sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">));</=
span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #800;" class=3D"styled-by-prettify">//Ign=
oring
                  obvious alignment issues here</span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"><br>
                  foo</span><span style=3D"color: #660;"
                  class=3D"styled-by-prettify">(</span><span style=3D"color=
:
                  #000;" class=3D"styled-by-prettify">__temp</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> a</s=
pan><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> b</s=
pan><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">);</s=
pan><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #800;" class=3D"styled-by-prettify">//Foo
                  knows how to offset into the temporary memory to store
                  each return value.</span><span style=3D"color: #000;"
                  class=3D"styled-by-prettify"><br>
                  T </span><span style=3D"color: #660;"
                  class=3D"styled-by-prettify">&amp;</span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">t </s=
pan><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> =C2=
=A0</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">*(</s=
pan><span
                  style=3D"color: #008;" class=3D"styled-by-prettify">reint=
erpret_cast</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">&lt;<=
/span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">T</sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">*&gt;=
(</span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">__tem=
p</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">));</=
span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"><br>
                  U </span><span style=3D"color: #660;"
                  class=3D"styled-by-prettify">&amp;</span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">u </s=
pan><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">*(</s=
pan><span
                  style=3D"color: #008;" class=3D"styled-by-prettify">reint=
erpret_cast</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">&lt;<=
/span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">U</sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">*&gt;=
(</span><span
                  style=3D"color: #008;" class=3D"styled-by-prettify">reint=
erpret_cast</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">&lt;<=
/span><span
                  style=3D"color: #008;" class=3D"styled-by-prettify">char<=
/span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">*&gt;=
(</span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">__tem=
p</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">)</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">+</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #008;" class=3D"styled-by-prettify">sizeo=
f</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">T</sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">)));<=
/span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #800;" class=3D"styled-by-prettify">//Aga=
in
                  ignore alignment</span><span style=3D"color: #000;"
                  class=3D"styled-by-prettify"><br>
                  V </span><span style=3D"color: #660;"
                  class=3D"styled-by-prettify">&amp;</span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">v </s=
pan><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">*(</s=
pan><span
                  style=3D"color: #008;" class=3D"styled-by-prettify">reint=
erpret_cast</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">&lt;<=
/span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">V</sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">*&gt;=
(</span><span
                  style=3D"color: #008;" class=3D"styled-by-prettify">reint=
erpret_cast</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">&lt;<=
/span><span
                  style=3D"color: #008;" class=3D"styled-by-prettify">char<=
/span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">*&gt;=
(</span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">__tem=
p</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">)</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">+</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #008;" class=3D"styled-by-prettify">sizeo=
f</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">T</sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">)</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">+</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #008;" class=3D"styled-by-prettify">sizeo=
f</span><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
                  style=3D"color: #000;" class=3D"styled-by-prettify">U</sp=
an><span
                  style=3D"color: #660;" class=3D"styled-by-prettify">)));<=
/span><span
                  style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
                  style=3D"color: #800;" class=3D"styled-by-prettify">//Aga=
in
                  ignore alignment</span><span style=3D"color: #000;"
                  class=3D"styled-by-prettify"><br>
                </span></div>
            </code></div>
          <br>
        </div>
      </div>
    </blockquote>
    And this is why I chose pseudocode.<br>
    <blockquote
      cite=3D"mid:9f3a42b5-befc-42e9-b739-654675eb4e02@isocpp.org"
      type=3D"cite">
      <div dir=3D"ltr">
        <div>This way, we don't have to think in terms of explicit=C2=A0
          "structs"; it's all just memory and ABI layout.<br>
          <br>
        </div>
        <blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
          0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
          This assumes all three types are copyable or at least movable
          to their final destination.
          <br>
        </blockquote>
        <div><br>
          If you ever do `T t =3D foo();`, the compiler <i>requires</i>
          that no there is an accessible copy/move constructor. The
          copy/move operation may be elided, but it still must be
          accessible.<br>
          =C2=A0</div>
        <blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
          0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">In the
          case where all three return values are used for initialization
          this is pretty trivial.
          <br>
          <br>
          T t, U u, V v =3D bar(a, b);
          <br>
          <br>
          transforms into
          <br>
          <br>
          #1
          <br>
          __Result __result; // not initialized
          <br>
          bar(&amp;__result, a, b);
          <br>
          // t, u, v are now aliases to __result.t, __result.u,
          __result.v
          <br>
          <br>
          Now what if the initialization is different
          <br>
          <br>
          #2
          <br>
          T t;
          <br>
          U u;
          <br>
          t, u, V v =3D bar(a, b);
          <br>
          <br>
          This must be transformed to <br>
          <br>
          __Result __result; // not initialized
          <br>
          bar(&amp;__result, A a, B b);
          <br>
          // v is now an alias to result.v
          <br>
          t =3D std::move(__result.t);
          <br>
          u =3D std::move(__result.u);
          <br>
          __result.u.~U();
          <br>
          __result.t.~T();
          <br>
          <br>
          This means there is wasted stack space for t and u (due to the
          fixed layout of __Result) __result.t and __result.u have to
          stay until v goes out of scope. It could be recycled for other
          variables, but just saying.<br>
        </blockquote>
        <div><br>
          How is that any different from the single return value case,
          when you store the result into a live object? Of course you
          have to copy/move the result into it. Elision only when when
          you <i>initializing</i> the return value.<br>
          <br>
          MRV doesn't change that in any way. <br>
        </div>
      </div>
    </blockquote>
    I didn't claim it changes anything. Here we only *initialize* one
    object, the other two are temporaries assigned to live objects.<br>
    <blockquote
      cite=3D"mid:9f3a42b5-befc-42e9-b739-654675eb4e02@isocpp.org"
      type=3D"cite">
      <div dir=3D"ltr">
        <div>=C2=A0</div>
        <blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
          0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
          I guess my whole point here is that there are at least two
          ways to implement this that need to be hammered into the ABI
          and dictate how much flexibility the caller has and how much
          call overhead there is per return value (1 or n additional
          pointers pushed). Once there is a syntax for this
          compiler-generated unpacking it can surely be extended to
          user-defined types. I just don=E2=80=99t think that there is as m=
uch
          elision potential for user-defined types.</blockquote>
        <div><br>
          Except that there's plenty of elision of potential for
          user-defined types. Indeed, modern C++ syntax is designed
          around the assumption that elision exists and will make code
          as fast as possible. Every time you see someone write `T t =3D
          stuff();` instead of an explicit `stuff(&amp;t, );`, you are
          implicitly relying on elision to make this fast.<br>
          <br>
          Why should MRVs undo this syntactic progress?<br>
        </div>
      </div>
    </blockquote>
    They shouldn't! My whole point was that this is doable. In multiple
    ways. With elision. Transparent to the language user for built-in
    MRVs. In fact I'm supporting your side of the argument for not
    artificially force std::tuple into it. Ugh.<br>
  </body>
</html>

<p></p>

-- <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+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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--------------020902030005000301030404--

.
