Topic: Core Language featuMultiple assignments
Author: Miro Knejp <miro.knejp@gmail.com>
Date: Tue, 26 May 2015 18:50:57 +0200
Raw View
Just an FYI: there might be a conflict with the Objective-C language, speci=
fically the Objective-C++ dialect, where "[x foo]" is the member function c=
alling syntax. Something to keep in mind as I=E2=80=99d be very surprised i=
f there weren=E2=80=99t committee members with an interest to keep C++ comp=
atible to said dialect.
> On 26 May 2015, at 18:09 , Matthew Woehlke <mw_triad@users.sourceforge.ne=
t> wrote:
>=20
> On 2015-05-20 21:14, Matthew Fioravante wrote:
>> I've chosen to use [] instead of {} [...]
>=20
> Given the syntax comments, I would encourage you to read the previous
> thread(s). That said, I have to say I'm actually in favor of the []
> syntax; it "feels" least likely to have parsing issues, and [] normally
> being indexing operators, it makes sense to me to use them for
> unpacking. (It probably also helps that I write the odd bit of Python,
> and Python uses [] to write lists :-).)
>=20
>> I've chosen to use ; instead of , to avoid confusion with the comma=20
>> operator.
>=20
> I strongly agree with using ';' to separate elements, since multiple
> declarations should be permitted, but '[auto x, auto y]' clearly makes
> no syntactic sense. That said, is ',' allowed inside the []'s at all? If
> yes, what does it mean?
>=20
> [auto x, y] =3D bar(); // forces decltype(x) =3D=3D decltype(y)?
>=20
>> We can also allow the user to specify a shorter list, with default value=
s=20
>> of void for the trailing elements not mentioned:
>>=20
>> [auto x] =3D foo(); //same as [auto x, void, void] =3D foo()
>=20
> I'd be somewhat strongly inclined to follow Python, and not discard any
> values. So the last item in the list becomes a tuple of whatever is left
> over.
>=20
> So, to take only the first value, you would write:
>=20
> [auto x; void] =3D foo();
>=20
> I also wonder if it should be an error if the number of arguments don't
> match, and require '...' to allow an item to expand to a (partial)
> tuple. For example:
>=20
> // assume foo() -> tuple<int, double, int>
> [auto x; void...] =3D foo(); // like above
> [auto x; auto... y] =3D foo(); // decltype(y) =3D=3D tuple<double, int>
>=20
> The down side of course is that this (except the 'void...' case)
> requires the compiler to know how many items are in the result. For
> tuple this is probably easy. For "generic" types it may be harder, but I
> imagine if necessary we could introduce a companion to std::get to
> return the largest index that can be used with std::get, if we don't
> already have ways to accomplish that.
>=20
>> What do you think about such a feature?
>=20
> As you may recall from (at least one of) the time(s) this came up
> previously, I am in favor of this :-).
>=20
> This may be implied anyway, but I'll say it explicitly; let's please
> also support this in range-based for:
>=20
> for ([auto key; auto value] : some_map) { ... }
>=20
> --=20
> Matthew
>=20
> --=20
>=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=
email 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-propo=
sals/.
--=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/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Tue, 26 May 2015 11:33:26 -0700
Raw View
On Tuesday 26 May 2015 11:10:11 Nicol Bolas wrote:
> Using the `[]` syntax noted here, you could have matching return and
> capture:
>
> [int,float,double] foo()
> {
> return [5; 23.4f; 10447.023d];
> }
I think the matching return and capture is a very important point, since a
lambda and this return are both basically anonymous structs.
return [x = 5, y = 10] {}
If it were possible to extract the captured variables, we'd have half the job
done.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Matthew Fioravante <fmatthew5876@gmail.com>
Date: Tue, 26 May 2015 11:47:42 -0700 (PDT)
Raw View
------=_Part_4618_33968875.1432666062666
Content-Type: multipart/alternative;
boundary="----=_Part_4619_1831715670.1432666062666"
------=_Part_4619_1831715670.1432666062666
Content-Type: text/plain; charset=UTF-8
On Tuesday, May 26, 2015 at 2:34:23 PM UTC-4, Thiago Macieira wrote:
>
>
> I think the matching return and capture is a very important point, since a
> lambda and this return are both basically anonymous structs.
>
> return [x = 5, y = 10] {}
>
> If it were possible to extract the captured variables, we'd have half the
> job
> done.
>
I'm not sure returning an anonymous type is actually desirable at all for
this feature. Lambda types are anonymous because they have a function call
operator that can do whatever and the type system cannot compare the
behavior of 2 lambdas operator() to prove they behave identically. An
[int,float,double] on the other hand does not need to be anonymous because
there is no ambiguity. Its just a type list like container holding these 3
objects.
Anonymous types come with a lot of baggage
- We have to use auto as the return type of the function, which for a large
function can reduce readability.
- Any function returning multiple values will need to be written in the
header file, no out of line functions allowed. (this is really bad imo)
- The function body can only have 1 return statement, as each invocation
returns a different anonymous type.
Is there any feature of an anonymous type that is actually beneficial?
A proposal that just defines a syntax sugar for defining a tuple type and a
syntax sugar for generating optimal code to extract values from tuple would
be simple to understand and give us the multiple return value idiom as
first class citizens in C++.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_4619_1831715670.1432666062666
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, May 26, 2015 at 2:34:23 PM UTC-4, Thia=
go Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><br>I think =
the matching return and capture is a very important point, since a=20
<br>lambda and this return are both basically anonymous structs.
<br>
<br> return [x =3D 5, y =3D =
10] {}
<br>
<br>If it were possible to extract the captured variables, we'd have half t=
he job=20
<br>done.
<br></blockquote><div><br>I'm not sure returning an anonymous type is actua=
lly desirable at all for this feature. Lambda types are anonymous because t=
hey have a function call operator that can do whatever and the type system =
cannot compare the behavior of 2 lambdas operator() to prove they behave id=
entically. An [int,float,double] on the other hand does not need to be anon=
ymous because there is no ambiguity. Its just a type list like container ho=
lding these 3 objects.<br><br>Anonymous types come with a lot of baggage<br=
>- We have to use auto as the return type of the function, which for a larg=
e function can reduce readability.<br>- Any function returning multiple val=
ues will need to be written in the header file, no out of line functions al=
lowed. (this is really bad imo)<br>- The function body can only have 1 retu=
rn statement, as each invocation returns a different anonymous type.<br><br=
>Is there any feature of an anonymous type that is actually beneficial?<br>=
<br>A proposal that just defines a syntax sugar for defining a tuple type a=
nd a syntax sugar for generating optimal code to extract values from tuple =
would be simple to understand and give us the multiple return value idiom a=
s first class citizens in C++.<br><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
------=_Part_4619_1831715670.1432666062666--
------=_Part_4618_33968875.1432666062666--
.
Author: Miro Knejp <miro.knejp@gmail.com>
Date: Tue, 26 May 2015 20:49:54 +0200
Raw View
The question here is really whether you want
1. a syntax and language support for multiple return values
or
2. a destructuring syntax for tuple/pair (or anything compatible with
unqualified get<N>(x))
These are orthogonal features.
1 brings along a big changelog, I don't even want to imagine how many
parts of the standard would need to be touched to integrate multiple
return values into functions, lambdas, and all the other funny corner
cases involving return values.
2 is a much more isolated change and would give multiple return values
"for free" to anything returning tuples/pairs. One might then think
about a convenient shorthand syntax for declaring tuple types. However
that than begs the question of whether one requires to include <tuple>
when using a language feature (as is technically required for
initializer_list) which is kinda awkward to be honest.
Am 26.05.2015 um 20:33 schrieb Thiago Macieira:
> On Tuesday 26 May 2015 11:10:11 Nicol Bolas wrote:
>> Using the `[]` syntax noted here, you could have matching return and
>> capture:
>>
>> [int,float,double] foo()
>> {
>> return [5; 23.4f; 10447.023d];
>> }
> I think the matching return and capture is a very important point, since a
> lambda and this return are both basically anonymous structs.
>
> return [x = 5, y = 10] {}
>
> If it were possible to extract the captured variables, we'd have half the job
> done.
>
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 26 May 2015 13:31:58 -0700 (PDT)
Raw View
------=_Part_602_1739277255.1432672319021
Content-Type: multipart/alternative;
boundary="----=_Part_603_485421821.1432672319021"
------=_Part_603_485421821.1432672319021
Content-Type: text/plain; charset=UTF-8
On Tuesday, May 26, 2015 at 2:49:38 PM UTC-4, Miro Knejp wrote:
>
> The question here is really whether you want
> 1. a syntax and language support for multiple return values
> or
> 2. a destructuring syntax for tuple/pair (or anything compatible with
> unqualified get<N>(x))
>
> These are orthogonal features.
>
Sort of.
We already have a way to deconstruct tuples/pairs: `std::tie`. So what is
being suggested is specialized syntax for it.
However, the principle justification for making that a language syntax (as
stated here in the OP) is for multiple return values. So if you have
multiple return values as legitimate syntax, you lose about 80% of the
reason for having tuple unpacking syntax.
Oh sure, people can still make use of it. But when you're talking about
adding new syntax for something, you need a really good justification for
it. And if multiple return values were a first-class C++ feature, then
tuple unpacking syntax would loose its major justifying purpose. And thus
it would probably never happen.
So while they're not technically orthogonal, it's highly unlikely that we'd
ever get both.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_603_485421821.1432672319021
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, May 26, 2015 at 2:49:38 PM UTC-4, Miro Knejp w=
rote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;">The question here is real=
ly whether you want
<br>1. a syntax and language support for multiple return values
<br>or
<br>2. a destructuring syntax for tuple/pair (or anything compatible with=
=20
<br>unqualified get<N>(x))
<br>
<br>These are orthogonal features.<br></blockquote><div><br>Sort of.<br><br=
>We already have a way to deconstruct tuples/pairs: `std::tie`. So what is =
being suggested is specialized syntax for it.<br><br>However, the principle=
justification for making that a language syntax (as stated here in the OP)=
is for multiple return values. So if you have multiple return values as le=
gitimate syntax, you lose about 80% of the reason for having tuple unpackin=
g syntax.<br><br>Oh sure, people can still make use of it. But when you're =
talking about adding new syntax for something, you need a really good justi=
fication for it. And if multiple return values were a first-class C++ featu=
re, then tuple unpacking syntax would loose its major justifying purpose. A=
nd thus it would probably never happen.<br><br>So while they're not technic=
ally orthogonal, it's highly unlikely that we'd ever get both.</div><br></d=
iv>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
------=_Part_603_485421821.1432672319021--
------=_Part_602_1739277255.1432672319021--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Tue, 26 May 2015 16:15:34 -0700
Raw View
On Tuesday 26 May 2015 13:00:50 Matthew Fioravante wrote:
> Is there any real reason to actually support anything other than tuple
> (with implicit conversion from pair) and array?
Are we talking about std::tuple or std::__1::tuple? And if it's std::tuple, do
you mean the one from GCC's libstdc++ or the STLport one, on Android?
Those types do not need to be layout compatible, especially when it comes to
empty member optimisations and optimising of padding.
std::initializer_list was specified as part of the initialiser list feature, so
ABIs defined it in those terms too; std::tuple did not benefit from that. So
this feature cannot rely on std::tuple, but must instead have its own ABI-
dependent type that std::tuple could construct constexprly from.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: David Krauss <potswa@gmail.com>
Date: Wed, 27 May 2015 09:41:15 +0800
Raw View
--Apple-Mail=_67A4468C-6527-4F64-8E94-516423E28FF9
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9305=E2=80=9327, at 8:14 AM, Nicol Bolas <jmckesson@gmail.c=
om <mailto:jmckesson@gmail.com>> wrote:
>=20
> ... std::tie takes a tuple and exports the members of that tuple into var=
iables. The opposite of that would be to take variables and combine them in=
to a tuple. That's called `make_tuple` <http://en.cppreference.com/w/cpp/ut=
ility/tuple/make_tuple>; you don't need special syntax for that.
>=20
> Also, I have no idea what that has to do with multiple return values.
The problem is that the variables need to be pre-existing, and support defa=
ult-initialization.
I don=E2=80=99t see why the preprocessor can=E2=80=99t do it. Translate
UNTIE( (a) (b) (c), expression )
into
auto && TUPLE_abc_init =3D expression;
static_assert ( is_rvalue_reference_to_tuple_v< decltype (TUPLE_abc_init) >=
, =E2=80=9COnly tuple values can be untied=E2=80=9D );
auto && a =3D std::get<0>( std::move( TUPLE_abc_init ) );
auto && b =3D std::get<0+1>( std::move( TUPLE_abc_init ) );
auto && c =3D std::get<0+1+1>( std::move( TUPLE_abc_init ) );
It=E2=80=99s at least a starting point=E2=80=A6
--=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/.
--Apple-Mail=_67A4468C-6527-4F64-8E94-516423E28FF9
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"><meta http-equiv=3D"Content-Type" content=3D"text/html charset=3D=
utf-8"><meta http-equiv=3D"Content-Type" content=3D"text/html charset=3Dutf=
-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: space; =
-webkit-line-break: after-white-space;" class=3D""><br class=3D""><div clas=
s=3D""><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=
=9305=E2=80=9327, at 8:14 AM, Nicol Bolas <<a href=3D"mailto:jmckesson@g=
mail.com" class=3D"">jmckesson@gmail.com</a>> wrote:</div><br class=3D"A=
pple-interchange-newline"><div class=3D""><div dir=3D"ltr" class=3D"">... s=
td::tie takes a tuple and exports the members of that tuple into variables.=
The opposite of that would be to take variables and combine them into a tu=
ple. That's called <a href=3D"http://en.cppreference.com/w/cpp/utility/tupl=
e/make_tuple" class=3D"">`make_tuple`</a>; you don't need special syntax fo=
r that.<br class=3D""><div class=3D""><br class=3D"">Also, I have no idea w=
hat that has to do with multiple return values.<br class=3D""></div></div><=
/div></blockquote><br class=3D""></div><div class=3D"">The problem is that =
the variables need to be pre-existing, and support default-initialization.<=
/div><div class=3D""><br class=3D""></div>I don=E2=80=99t see why the prepr=
ocessor can=E2=80=99t do it. Translate<div class=3D""><br class=3D""></div>=
<div class=3D""><font face=3D"Courier" class=3D"">UNTIE( (a) (b) (c), expre=
ssion )</font></div><div class=3D""><br class=3D""></div><div class=3D"">in=
to</div><div class=3D""><br class=3D""></div><div class=3D""><font face=3D"=
Courier" class=3D"">auto && TUPLE_abc_init =3D expression;</font></=
div><div class=3D""><font face=3D"Courier" class=3D"">static_assert ( is_rv=
alue_reference_to_tuple_v< decltype (TUPLE_abc_init) >, =E2=80=9COnly=
tuple values can be untied=E2=80=9D );</font></div><div class=3D""><font f=
ace=3D"Courier" class=3D"">auto && a =3D std::get<0>( std::mo=
ve( TUPLE_abc_init ) );</font></div><div class=3D""><font face=3D"Courier" =
class=3D"">auto && b =3D std::get<0+1>( std::move( TUPLE=
_abc_init ) );</font></div><div class=3D""><div class=3D""><font face=3D"Co=
urier" class=3D"">auto && c =3D std::get<0+1+1>( std::mo=
ve( TUPLE_abc_init ) );</font></div></div><div class=3D""><br class=3D""></=
div><div class=3D"">It=E2=80=99s at least a starting point=E2=80=A6</div></=
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" 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 />
--Apple-Mail=_67A4468C-6527-4F64-8E94-516423E28FF9--
.
Author: Miro Knejp <miro.knejp@gmail.com>
Date: Wed, 27 May 2015 10:51:50 +0200
Raw View
--Apple-Mail=_3DF0C2DE-72E6-476C-99F6-D723A7EC6453
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 27 May 2015, at 09:43 , Nicol Bolas <jmckesson@gmail.com> wrote:
>=20
>=20
> [int,long,double] foo();
> auto x =3D foo();
>=20
> Ok, if tuple is out then what is decltype(x) in the above example doing t=
hings your way?
>=20
> There are two defensible answers to this:
>=20
> 1) A compilation error. You called a function that returns 3 things, but =
you only captured one. That suggests you weren't paying attention.
>=20
> 2) `int`. The other two types are dropped on the floor.
>=20
> #2 is probably the way to go. Any sort of aggregate object type is not ev=
en up for discussion.
>=20
> Multiple return values means multiple return values, not "pack multiple v=
alues into some kind of object and unpack them later".
> =20
> Another kind of typelist which is standard layout compatible? Or are we n=
o longer able to capture all of the return values into one object?
>=20
> If you want to capture them all in an object, you just ask for it:
>=20
> auto x =3D make_tuple(foo());
>=20
> That is neither hard nor particularly verbose. You can even stick them in=
an array, if all of the returned values are of the same type:
>=20
> auto x =3D make_array(foo());
>=20
> Or in an arbitrary data structure:
>=20
> auto x =3D std::vector<Type>{foo()};
>=20
> But most people using multiple return values don't capture them in a big =
object, so we don't make the syntax optimal for that case.
>=20
I assume Matthew=E2=80=99s point comes from dealing with template code.
template<class F>
??? contrived_example(F f) {
return f();
}
The author would probably expect that ??? can be plain =E2=80=9Cauto=E2=80=
=9D, implying =E2=80=9Cin some places auto can expand to multiple types=E2=
=80=9D. Then there=E2=80=99s the point of what generic code would require t=
o do to consistently capture the return value(s) of a Callable without know=
ing if there are one or multiple return values.
template<class F>
void contrived_example2(F f) {
??? x =3D f();
...
}
Should ??? be something that can potentially capture a single or multiple v=
alues depending on the initialization? If so what can be done with x down t=
he pipeline? Or is a concept necessary to overload contrived_example2 for f=
unctions with single or multiple return values? Is template code forced int=
o packing every Callable=E2=80=99s invocation into make_tuple() just in cas=
e it might return multiple values?
--=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/.
--Apple-Mail=_3DF0C2DE-72E6-476C-99F6-D723A7EC6453
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 27 May 2015, at 0=
9:43 , Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.com" class=3D"">jm=
ckesson@gmail.com</a>> wrote:</div><br class=3D"Apple-interchange-newlin=
e"><div class=3D""><div dir=3D"ltr" style=3D"font-family: Helvetica; font-s=
ize: 12px; font-style: normal; font-variant: normal; font-weight: normal; l=
etter-spacing: normal; line-height: normal; orphans: auto; text-align: star=
t; text-indent: 0px; text-transform: none; white-space: normal; widows: aut=
o; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D""><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left-wi=
dth: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; =
padding-left: 1ex;"><div dir=3D"ltr" class=3D""><div class=3D""><br class=
=3D""></div><div class=3D""><div style=3D"border: 1px solid rgb(187, 187, 1=
87); word-wrap: break-word; background-color: rgb(250, 250, 250);" class=3D=
""><code class=3D""><span style=3D"color: rgb(102, 102, 0);" class=3D"">[</=
span><span style=3D"color: rgb(0, 0, 136);" class=3D"">int</span><span styl=
e=3D"color: rgb(102, 102, 0);" class=3D"">,</span><span style=3D"color: rgb=
(0, 0, 136);" class=3D"">long</span><span style=3D"color: rgb(102, 102, 0);=
" class=3D"">,</span><span style=3D"color: rgb(0, 0, 136);" class=3D"">doub=
le</span><span style=3D"color: rgb(102, 102, 0);" class=3D"">]</span><span =
class=3D"Apple-converted-space"> </span>foo<span style=3D"color: rgb(1=
02, 102, 0);" class=3D"">();</span><br class=3D""><span style=3D"color: rgb=
(0, 0, 136);" class=3D"">auto</span><span style=3D"" class=3D""><span class=
=3D"Apple-converted-space"> </span>x<span class=3D"Apple-converted-spa=
ce"> </span></span><span style=3D"color: rgb(102, 102, 0);" class=3D""=
>=3D</span><span class=3D"Apple-converted-space"> </span>foo<span styl=
e=3D"color: rgb(102, 102, 0);" class=3D"">();</span><font color=3D"#666600"=
class=3D""></font></code></div><br class=3D""></div><div class=3D"">Ok, if=
tuple is out then what is decltype(x) in the above example doing things yo=
ur way?</div></div></blockquote><div class=3D""><br class=3D"">There are tw=
o defensible answers to this:<br class=3D""><br class=3D"">1) A compilation=
error. You called a function that returns 3 things, but you only captured =
one. That suggests you weren't paying attention.<br class=3D""><br class=3D=
"">2) `int`. The other two types are dropped on the floor.<br class=3D""><b=
r class=3D"">#2 is probably the way to go. Any sort of aggregate object typ=
e is not even up for discussion.<br class=3D""><br class=3D"">Multiple retu=
rn values means<span class=3D"Apple-converted-space"> </span><i class=
=3D"">multiple return values</i>, not "pack multiple values into some kind =
of object and unpack them later".<br class=3D""> </div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left-width: 1=
px; border-left-color: rgb(204, 204, 204); border-left-style: solid; paddin=
g-left: 1ex;"><div dir=3D"ltr" class=3D""><div class=3D"">Another kind of t=
ypelist which is standard layout compatible? Or are we no longer able to ca=
pture all of the return values into one object?</div></div></blockquote><di=
v class=3D""><br class=3D"">If you want to capture them all in an object, y=
ou just ask for it:<br class=3D""><br class=3D""><div class=3D"prettyprint"=
style=3D"background-color: rgb(250, 250, 250); border: 1px solid rgb(187, =
187, 187); word-wrap: break-word;"><code class=3D"prettyprint"><span class=
=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">auto</span><span c=
lass=3D"styled-by-prettify" style=3D""><span class=3D"Apple-converted-space=
"> </span>x<span class=3D"Apple-converted-space"> </span></span><=
span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">=3D</s=
pan><span class=3D"Apple-converted-space"> </span>make_tuple<span clas=
s=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">(</span>foo<spa=
n class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">());</spa=
n></code></div><br class=3D"">That is neither hard nor particularly verbose=
.. You can even stick them in an array, if all of the returned values are of=
the same type:<br class=3D""><br class=3D""><div class=3D"prettyprint" sty=
le=3D"background-color: rgb(250, 250, 250); border: 1px solid rgb(187, 187,=
187); word-wrap: break-word;"><code class=3D"prettyprint"><span class=3D"s=
tyled-by-prettify" style=3D"color: rgb(0, 0, 136);">auto</span><span class=
=3D"styled-by-prettify" style=3D""><span class=3D"Apple-converted-space">&n=
bsp;</span>x<span class=3D"Apple-converted-space"> </span></span><span=
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">=3D</span>=
<span class=3D"Apple-converted-space"> </span>make_array<span class=3D=
"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">(</span>foo<span cl=
ass=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">());</span></=
code></div><br class=3D"">Or in an arbitrary data structure:<br class=3D"">=
<br class=3D""><div class=3D"prettyprint" style=3D"background-color: rgb(25=
0, 250, 250); border: 1px solid rgb(187, 187, 187); word-wrap: break-word;"=
><code class=3D"prettyprint"><span class=3D"styled-by-prettify" style=3D"co=
lor: rgb(0, 0, 136);">auto</span><span class=3D"styled-by-prettify" style=
=3D""><span class=3D"Apple-converted-space"> </span>x<span class=3D"Ap=
ple-converted-space"> </span></span><span class=3D"styled-by-prettify"=
style=3D"color: rgb(102, 102, 0);">=3D</span><span class=3D"Apple-converte=
d-space"> </span>std<span class=3D"styled-by-prettify" style=3D"color:=
rgb(102, 102, 0);">::</span>vector<span class=3D"styled-by-prettify" style=
=3D"color: rgb(102, 102, 0);"><</span><span class=3D"styled-by-prettify"=
style=3D"color: rgb(102, 0, 102);">Type</span><span class=3D"styled-by-pre=
ttify" style=3D"color: rgb(102, 102, 0);">>{</span>foo<span class=3D"sty=
led-by-prettify" style=3D"color: rgb(102, 102, 0);">()};</span><br class=3D=
""></code></div><br class=3D"">But most people using multiple return values=
don't capture them in a big object, so we don't make the syntax optimal fo=
r that case.<br class=3D""><br class=3D""></div><blockquote class=3D"gmail_=
quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-l=
eft-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;=
"><div dir=3D"ltr" class=3D""><div class=3D""></div></div></blockquote></di=
v></div></blockquote></div><div class=3D""><br class=3D""></div>I assume Ma=
tthew=E2=80=99s point comes from dealing with template code.<div class=3D""=
><br class=3D""></div><div class=3D"">template<class F></div><div cla=
ss=3D"">??? contrived_example(F f) {</div><div class=3D""> ret=
urn f();</div><div class=3D"">}</div><div class=3D""><br class=3D""></div><=
div class=3D"">The author would probably expect that ??? can be plain =E2=
=80=9Cauto=E2=80=9D, implying =E2=80=9Cin some places auto can expand to mu=
ltiple types=E2=80=9D. Then there=E2=80=99s the point of what generic code =
would require to do to consistently capture the return value(s) of a Callab=
le without knowing if there are one or multiple return values.</div><div cl=
ass=3D""><br class=3D""></div><div class=3D"">template<class F></div>=
<div class=3D"">void contrived_example2(F f) {</div><div class=3D""> =
??? x =3D f();</div><div class=3D""> ...</div><div clas=
s=3D"">}</div><div class=3D""><br class=3D""></div><div class=3D"">Should ?=
?? be something that can potentially capture a single or multiple values de=
pending on the initialization? If so what can be done with x down the pipel=
ine? Or is a concept necessary to overload contrived_example2 for functions=
with single or multiple return values? Is template code forced into packin=
g every Callable=E2=80=99s invocation into make_tuple() just in case it mig=
ht return multiple values?</div><div class=3D""><br class=3D""></div></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" 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 />
--Apple-Mail=_3DF0C2DE-72E6-476C-99F6-D723A7EC6453--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 27 May 2015 08:11:00 -0700 (PDT)
Raw View
------=_Part_583_703389892.1432739460260
Content-Type: multipart/alternative;
boundary="----=_Part_584_2123921756.1432739460260"
------=_Part_584_2123921756.1432739460260
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, May 27, 2015 at 4:51:58 AM UTC-4, Miro Knejp wrote:
>
>
> On 27 May 2015, at 09:43 , Nicol Bolas <jmck...@gmail.com <javascript:>>=
=20
> wrote:
>
>
>> [int,long,double] foo();
>> auto x =3D foo();
>>
>> Ok, if tuple is out then what is decltype(x) in the above example doing=
=20
>> things your way?
>>
>
> There are two defensible answers to this:
>
> 1) A compilation error. You called a function that returns 3 things, but=
=20
> you only captured one. That suggests you weren't paying attention.
>
> 2) `int`. The other two types are dropped on the floor.
>
> #2 is probably the way to go. Any sort of aggregate object type is not=20
> even up for discussion.
>
> Multiple return values means *multiple return values*, not "pack multiple=
=20
> values into some kind of object and unpack them later".
> =20
>
>> Another kind of typelist which is standard layout compatible? Or are we=
=20
>> no longer able to capture all of the return values into one object?
>>
>
> If you want to capture them all in an object, you just ask for it:
>
> auto x =3D make_tuple(foo());
>
> That is neither hard nor particularly verbose. You can even stick them in=
=20
> an array, if all of the returned values are of the same type:
>
> auto x =3D make_array(foo());
>
> Or in an arbitrary data structure:
>
> auto x =3D std::vector<Type>{foo()};
>
> But most people using multiple return values don't capture them in a big=
=20
> object, so we don't make the syntax optimal for that case.
>
>
> I assume Matthew=E2=80=99s point comes from dealing with template code.
>
> template<class F>
> ??? contrived_example(F f) {
> return f();
> }
>
> The author would probably expect that ??? can be plain =E2=80=9Cauto=E2=
=80=9D, implying=20
> =E2=80=9Cin some places auto can expand to multiple types=E2=80=9D.
>
Well, `auto` as a "return type" means something very different from `auto`=
=20
as a variable declaration. So it's perfectly reasonable for `auto` or=20
`decltype(auto)` to deduce multiple return values. Just as it can deduce=20
`void` (ie: zero return values).
=20
> Then there=E2=80=99s the point of what generic code would require to do t=
o=20
> consistently capture the return value(s) of a Callable without knowing if=
=20
> there are one or multiple return values.
>
> template<class F>
> void contrived_example2(F f) {
> ??? x =3D f();
> ...
> }
>
That one's easy. Since you're in generic code and could be getting multiple=
=20
values, the only way to manipulate them is with a tuple. So that's what you=
=20
stick them in:
auto x =3D make_tuple(f());
--=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/.
------=_Part_584_2123921756.1432739460260
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, May 27, 2015 at 4:51:58 AM UTC-4, Mi=
ro Knejp wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"w=
ord-wrap:break-word"><br><div><blockquote type=3D"cite"><div>On 27 May 2015=
, at 09:43 , Nicol Bolas <<a href=3D"javascript:" target=3D"_blank" gdf-=
obfuscated-mailto=3D"ZhKGsYWWzngJ" rel=3D"nofollow" onmousedown=3D"this.hre=
f=3D'javascript:';return true;" onclick=3D"this.href=3D'javascript:';return=
true;">jmck...@gmail.com</a>> wrote:</div><br><div><div dir=3D"ltr" sty=
le=3D"font-family:Helvetica;font-size:12px;font-style:normal;font-variant:n=
ormal;font-weight:normal;letter-spacing:normal;line-height:normal;text-alig=
n:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing=
:0px"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr"><div><br></div><div><div style=3D"b=
order:1px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(=
250,250,250)"><code><span style=3D"color:rgb(102,102,0)">[</span><span styl=
e=3D"color:rgb(0,0,136)">int</span><span style=3D"color:rgb(102,102,0)">,</=
span><span style=3D"color:rgb(0,0,136)">long</span><span style=3D"color:rgb=
(102,102,0)">,</span><span style=3D"color:rgb(0,0,136)">double</span><span =
style=3D"color:rgb(102,102,0)">]</span><span> </span>foo<span style=3D=
"color:rgb(102,102,0)">();</span><br><span style=3D"color:rgb(0,0,136)">aut=
o</span><span><span> </span>x<span> </span></span><span style=3D"=
color:rgb(102,102,0)">=3D</span><span> </span>foo<span style=3D"color:=
rgb(102,102,0)">();</span><font color=3D"#666600"></font></code></div><br><=
/div><div>Ok, if tuple is out then what is decltype(x) in the above example=
doing things your way?</div></div></blockquote><div><br>There are two defe=
nsible answers to this:<br><br>1) A compilation error. You called a functio=
n that returns 3 things, but you only captured one. That suggests you weren=
't paying attention.<br><br>2) `int`. The other two types are dropped on th=
e floor.<br><br>#2 is probably the way to go. Any sort of aggregate object =
type is not even up for discussion.<br><br>Multiple return values means<spa=
n> </span><i>multiple return values</i>, not "pack multiple values int=
o some kind of object and unpack them later".<br> </div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px=
;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1e=
x"><div dir=3D"ltr"><div>Another kind of typelist which is standard layout =
compatible? Or are we no longer able to capture all of the return values in=
to one object?</div></div></blockquote><div><br>If you want to capture them=
all in an object, you just ask for it:<br><br><div style=3D"background-col=
or:rgb(250,250,250);border:1px solid rgb(187,187,187);word-wrap:break-word"=
><code><span style=3D"color:rgb(0,0,136)">auto</span><span><span> </sp=
an>x<span> </span></span><span style=3D"color:rgb(102,102,0)">=3D</spa=
n><span> </span>make_tuple<span style=3D"color:rgb(102,102,0)">(</span=
>foo<span style=3D"color:rgb(102,102,0)">());</span></code></div><br>That i=
s neither hard nor particularly verbose. You can even stick them in an arra=
y, if all of the returned values are of the same type:<br><br><div style=3D=
"background-color:rgb(250,250,250);border:1px solid rgb(187,187,187);word-w=
rap:break-word"><code><span style=3D"color:rgb(0,0,136)">auto</span><span><=
span> </span>x<span> </span></span><span style=3D"color:rgb(102,1=
02,0)">=3D</span><span> </span>make_array<span style=3D"color:rgb(102,=
102,0)">(</span>foo<span style=3D"color:rgb(102,102,0)">());</span></code><=
/div><br>Or in an arbitrary data structure:<br><br><div style=3D"background=
-color:rgb(250,250,250);border:1px solid rgb(187,187,187);word-wrap:break-w=
ord"><code><span style=3D"color:rgb(0,0,136)">auto</span><span><span> =
</span>x<span> </span></span><span style=3D"color:rgb(102,102,0)">=3D<=
/span><span> </span>std<span style=3D"color:rgb(102,102,0)">::</span>v=
ector<span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:r=
gb(102,0,102)">Type</span><span style=3D"color:rgb(102,102,0)">>{</span>=
foo<span style=3D"color:rgb(102,102,0)"><wbr>()};</span><br></code></div><b=
r>But most people using multiple return values don't capture them in a big =
object, so we don't make the syntax optimal for that case.<br><br></div><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-lef=
t-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padd=
ing-left:1ex"><div dir=3D"ltr"><div></div></div></blockquote></div></div></=
blockquote></div><div><br></div>I assume Matthew=E2=80=99s point comes from=
dealing with template code.<div><br></div><div>template<class F></di=
v><div>??? contrived_example(F f) {</div><div> return f();</di=
v><div>}</div><div><br></div><div>The author would probably expect that ???=
can be plain =E2=80=9Cauto=E2=80=9D, implying =E2=80=9Cin some places auto=
can expand to multiple types=E2=80=9D.</div></div></blockquote><div><br>We=
ll, `auto` as a "return type" means something very different from `auto` as=
a variable declaration. So it's perfectly reasonable for `auto` or `declty=
pe(auto)` to deduce multiple return values. Just as it can deduce `void` (i=
e: zero return values).<br> </div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div style=3D"word-wrap:break-word"><div> Then there=E2=80=99s the=
point of what generic code would require to do to consistently capture the=
return value(s) of a Callable without knowing if there are one or multiple=
return values.</div><div><br></div><div>template<class F></div><div>=
void contrived_example2(F f) {</div><div> ??? x =3D f();</div>=
<div> ...</div><div>}</div></div></blockquote><div><br>That on=
e's easy. Since you're in generic code and could be getting multiple values=
, the only way to manipulate them is with a tuple. So that's what you stick=
them in:<br><br>auto x =3D make_tuple(f());</div><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
------=_Part_584_2123921756.1432739460260--
------=_Part_583_703389892.1432739460260--
.
Author: Matthew Fioravante <fmatthew5876@gmail.com>
Date: Wed, 27 May 2015 08:11:34 -0700 (PDT)
Raw View
------=_Part_173_2103744840.1432739494049
Content-Type: multipart/alternative;
boundary="----=_Part_174_1468761672.1432739494049"
------=_Part_174_1468761672.1432739494049
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, May 27, 2015 at 3:43:10 AM UTC-4, Nicol Bolas wrote:
>
> In Lua, you don't need special syntax for returning or capturing multiple=
=20
> values. And quite frankly, I see no reason why you should:
>
> function foo()
> return 1, 2, 3 --Returns a sequence of 3 values.
> end
>
> function bar()
> return {1, 2, 3} --Returns a single table, containing 3 values
> end
>
> local x, y, z =3D foo() --Declares 3 local variables, initializing them w=
ith=20
> 3 values from the function.
>
> local w =3D {foo()} --Stores the sequence of values returned from `foo` i=
n=20
> a table (aka: array)
>
> local a =3D bar() --Stores the table
>
> local comp =3D bar(foo()) --The sequence is passed to `bar` as 3 paramete=
rs.
>
> local comp2 =3D bar(bar()) --A single parameter is passed to the outer `b=
ar`
> .
>
> local comp3 =3D bar(unpack(bar())) --Unpacks the array into the outer `ba=
r`'s=20
> parameters
>
> I find that much more reasonable and consistent than the Python syntax.=
=20
> There is a distinction between a sequence of values and a data structure.=
=20
> `foo` and `bar` may be "conceptually" the same, but functionally they're=
=20
> different. One returns a sequence of values, the other returns a table. I=
f=20
> you need to convert a table into a sequence of values, you call `unpack`.=
=20
> If you need to convert a sequence of values into a table, you create a=20
> table with it.
>
> Sequences of values in Lua are ephemeral; if you want to store the=20
> sequence and preserve it as a sequence, you stick it in a table. But if y=
ou=20
> just want to compose functions, store values, and the like, you use the=
=20
> sequence as is.
>
> If C++ is going to pattern its functionality off of something, I'd much=
=20
> rather Lua's proper MRV syntax than Python's MRVs-as-arrays (I assume the=
=20
> () syntax is creating an array of some kind).
>
We still need a special "unpacking" syntax to bind the multi return values=
=20
to variables because the comma operator is already taken and not sufficient=
=20
for this task. The following looks very confusing and it doesn't even=20
account for multiple return values of different types. It also doesn't let=
=20
us assign return values directly to pre-existing variables.
[int,int,int] foo();
int bar();
//Initializes x, y, z using foo's return values??
int x, y, z =3D foo();
//Initializes only c using bar's() return value and leaves a and b=20
uninitialized
int a, b, c =3D bar();
=20
We could allow using auto here:
[int,long,double] foo();
auto x, y, z =3D foo(); //x is int, y is long, z is double
But this still doesn't allow us to specify cv and ref qualifiers for the=20
individual variables.
=20
>
> =20
>>
>>
>>> As was stated earlier, doing it this way would be a huge change that=20
>>>> likely would never make it past the committee.
>>>>
>>>
>>> But it's the right way to do it. And quite frankly, we don't need=20
>>> multiple return values so badly that we should do it the wrong way just=
to=20
>>> have *some* convenient way to do it.
>>>
>>> Some people use tuples a lot (some might say to the point of overuse).=
=20
>>> But you shouldn't steal potentially useful syntax from those C++=20
>>> programmers who don't use them.=20
>>>
>>
>> Programmers who have no interest in tuple itself can just use the syntax=
=20
>> to return multiple values and unpack them at the call site. They don't h=
ave=20
>> to care that tuple (or something tuple like) is used to accomplish this.
>>
>
> Except that they have to pay the cost for it. Consider something simple=
=20
> like this:
>
> auto single_value()
> {
> std::string a =3D ...;
> return a;
> }
>
> auto multi_value()
> {
> std::string a =3D ...;
> std::vector b =3D ...;
> return [a; b];
> }
>
> `single_value` is subject to copy elision, so you should feel no problem=
=20
> with using it. Even with a small-string-optimized std::string class, you=
=20
> will get the maximum possible performance if you're using the result to=
=20
> initialize an object.
>
> With language-level multiple return values, `multi_value` would be able t=
o=20
> operate under the same principle. `a` and `b` would be considered return=
=20
> values, and they would each be separately subject to elision.
>
> With your way, that's just not possible. If that syntax creates a `tuple`=
,=20
> then it must copy or move initialize the elements of that `tuple`. So eve=
n=20
> though the `tuple` itself is subject to elision, the creation of it is no=
t.
>
So whats stopping someone from writing a proposal to allow copy/move=20
elision in your multi_value() example? Just because it can't happen now=20
doesn't mean we can't change the standard. Multi return values would be a=
=20
primary use case for such a proposal.
> =20
>>
>>> Syntax is a precious commodity, which once apportioned, cannot be taken=
=20
>>> back.
>>>
>>> It should also be noted that reflection, with the full ability to=20
>>> compile-time inspect and generate types with full syntax (including=20
>>> variable names) makes tuples... a dubious proposition for the future of=
=20
>>> C++. With reflection, you can index a struct by number. With reflection=
,=20
>>> you can take any typelist and build an honest-to-God struct out of it=
=20
>>> (which can be standard layout and such).
>>>
>>> In short, it is entirely possible that tuples will become obsolete, thu=
s=20
>>> also obsoleting this kind of syntax. So let's not have another std::bin=
d=20
>>> happen here...
>>>
>>
>> [int,long,double] foo();
>> auto x =3D foo();
>>
>> Ok, if tuple is out then what is decltype(x) in the above example doing=
=20
>> things your way?
>>
>
> There are two defensible answers to this:
>
> 1) A compilation error. You called a function that returns 3 things, but=
=20
> you only captured one. That suggests you weren't paying attention.
>
> 2) `int`. The other two types are dropped on the floor.
>
> #2 is probably the way to go. Any sort of aggregate object type is not=20
> even up for discussion.
>
Then I should also ask you how do you plan on capturing the multiple=20
values? Using a syntax similar to the one I proposed?
This looks bad:
[int,float] foo();
[auto x; auto y] =3D foo(); //Ok captures into x and y
[auto x; void] =3D foo(); //Ok captures first into x, throws away second
auto x =3D foo(); //Captures only first??
The last line there looks like an easy recipe for bugs, especially in=20
generic code. I would suggest making it a compiler error.
Also what if I want to save the sequence so that I can forward it multiple=
=20
times?
Using your approach, I might suggest allowing auto... to capture all of the=
=20
return values so that they can be forwarded along. This could work just=20
like a variadic template parameter pack.
void foo(int, float);
[int, float] bar();
auto... x =3D bar();
foo(x...);
foo(x...);
But we still have the generic code problems that Miro brought up.
=20
>
> Multiple return values means *multiple return values*, not "pack multiple=
=20
> values into some kind of object and unpack them later".
> =20
>
>> Another kind of typelist which is standard layout compatible? Or are we=
=20
>> no longer able to capture all of the return values into one object?
>>
>
> If you want to capture them all in an object, you just ask for it:
>
> auto x =3D make_tuple(foo());
>
> That is neither hard nor particularly verbose. You can even stick them in=
=20
> an array, if all of the returned values are of the same type:
>
> auto x =3D make_array(foo());
>
>
These require copy/move. In your example, unpacking is free (no-op) and=20
packing requires a copy/move. In my example unpacking is free (using=20
references) and packing is also free, assuming you want to continue using=
=20
the pack type returned by the function.=20
=20
> Or in an arbitrary data structure:
>
> auto x =3D std::vector<Type>{foo()};
>
> But most people using multiple return values don't capture them in a big=
=20
> object, so we don't make the syntax optimal for that case.
>
Its not uncommon. Every class that has multiple "values" (e.g=20
unordered_map) will be returning them in a pack using its default=20
iterators so that one can write a simple range for loop.
=20
>
> If not using tuple, can you explain in a bit more detail how your propose=
d=20
>> solution would actually work?
>>
>
> The details of how it works are more or less the way Lua works.
>
> In C++ parlance, the notion of a "sequence of values" would be a=20
> construct. It would *not* necessarily be an "expression", in the same way=
=20
> that a braced-init-list is not an expression. Since it's a new construct,=
=20
> you can give it whatever properties you want.
>
> Functions can return sequences of values, with the sequence as a full par=
t=20
> of its return type. Using the sequence initialization syntax, you can=20
> initialize/assign multiple variables to a sequence of values. If a sequen=
ce=20
> of values is given to a function argument list, the values are placed in=
=20
> that list as arguments. If the sequence of values is used in any other ki=
nd=20
> of expression, then it resolves down to the first element of that sequenc=
e=20
> of values.
>
> Initialization/assignment of variables through a sequence would work=20
> element by element, in order from left to right.
>
I would suggest maybe piggybacking off of varadic template parameter packs=
=20
(If they can fit into this feature) instead of inventing a yet another=20
brand new thing which is only used for multiple return values which itself=
=20
does not show up very often.
You mentioned reflection before. I believe with reflection, we can achieve=
=20
even better interfaces if we designed this MRV feature around unpacking=20
collections of objects.
For example, imagine if we could unpack a pod struct like this (implemented=
=20
using reflection):
struct kv {
string key;
int value;
};
kv kv;
[auto k; auto v] =3D kv;
Why is this so great? Here is an example:
template <typename K, typename V>
class HashMap {
public:
struct kv { K key; V value; };
class iterator : public std::iterator<std::bidirectional_iterator_tag,kv>=
=20
{ /* ... */ };
//...
};
HashMap hashmap =3D /* something */;
//Iterate using kv struct (more descriptive than pair)
for(auto& kv: hashmap) {
doSomething(kv.key, kv.value);
}
//Iterate by unpacking the kv struct first
for([auto& key; auto& value]: hashmap) {
doSomething(key, value);
}
//Iterate over only the keys
for([auto& key; void]: hashmap) {}
//Iterate over only the values
for([void; auto& value]: hashmap) {}
If the MRV feature is designed around unpacking collections of objects,=20
then we can get interfaces like this for free from reflection. All 4=20
example loops are enabled without any additional work by the author of=20
HashMap.=20
If MRV is designed using sequences, then the class author has to provide=20
separate iterators for returning an MRV sequence and also returning a pack=
=20
in the default iterators. Class designers are already overburdened with=20
boilerplate for writing type trait tags, iterator types, copy/move=20
constructors, comparison operators, swap operator, etc..=20
The Lua way of doing things might be elegant, but lua is also a very simple=
=20
language. It doesn't have the same features and restrictions of C++ and I'm=
=20
not sure yet if that approach would be the best way.
On Wednesday, May 27, 2015 at 4:51:58 AM UTC-4, Miro Knejp wrote:
>
> I assume Matthew=E2=80=99s point comes from dealing with template code.
>
> template<class F>
> ??? contrived_example(F f) {
> return f();
> }
>
> The author would probably expect that ??? can be plain =E2=80=9Cauto=E2=
=80=9D, implying=20
> =E2=80=9Cin some places auto can expand to multiple types=E2=80=9D. Then =
there=E2=80=99s the point=20
> of what generic code would require to do to consistently capture the retu=
rn=20
> value(s) of a Callable without knowing if there are one or multiple retur=
n=20
> values.
>
> template<class F>
> void contrived_example2(F f) {
> ??? x =3D f();
> ...
> }
>
> Should ??? be something that can potentially capture a single or multiple=
=20
> values depending on the initialization? If so what can be done with x dow=
n=20
> the pipeline? Or is a concept necessary to overload contrived_example2 fo=
r=20
> functions with single or multiple return values? Is template code forced=
=20
> into packing every Callable=E2=80=99s invocation into make_tuple() just i=
n case it=20
> might return multiple values?
>
>
These are very good questions. If multi return is just sugar for returning=
=20
a pack type, then generic code works just fine without any issue. If not,=
=20
then we have a lot of questions to answer.=20
--=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/.
------=_Part_174_1468761672.1432739494049
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, May 27, 2015 at 3:43:10 AM UTC-4, Ni=
col Bolas wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><br><div>In
Lua, you don't need special syntax for returning or capturing multiple=20
values. And quite frankly, I see no reason why you should:<br><br><div styl=
e=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border=
-style:solid;border-width:1px;word-wrap:break-word"><code><div><span style=
=3D"color:#008">function</span><span style=3D"color:#000"> foo</span><span =
style=3D"color:#660">()</span><span style=3D"color:#000"><br> </span>=
<span style=3D"color:#008">return</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#066">1</span><span style=3D"color:#660">,</span><span=
style=3D"color:#000"> </span><span style=3D"color:#066">2</span><span styl=
e=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"=
color:#066">3</span><span style=3D"color:#000"> </span><span style=3D"color=
:#660">--</span><span style=3D"color:#606">Returns</span><span style=3D"col=
or:#000"> a sequence of </span><span style=3D"color:#066">3</span><span sty=
le=3D"color:#000"> values</span><span style=3D"color:#660">.</span><span st=
yle=3D"color:#000"><br></span><span style=3D"color:#008">end</span><span st=
yle=3D"color:#000"><br><br></span><span style=3D"color:#008">function</span=
><span style=3D"color:#000"> bar</span><span style=3D"color:#660">()</span>=
<span style=3D"color:#000"><br> </span><span style=3D"color:#008">ret=
urn</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</=
span><span style=3D"color:#066">1</span><span style=3D"color:#660">,</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#066">2</span><span=
style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#066">3</span><span style=3D"color:#660">}</span><span style=3D"=
color:#000"> </span><span style=3D"color:#660">--</span><span style=3D"colo=
r:#606">Returns</span><span style=3D"color:#000"> a single table</span><spa=
n style=3D"color:#660">,</span><span style=3D"color:#000"> containing </spa=
n><span style=3D"color:#066">3</span><span style=3D"color:#000"> values<br>=
</span><span style=3D"color:#008">end</span><span style=3D"color:#000"><br>=
<br></span><span style=3D"color:#008">local</span><span style=3D"color:#000=
"> x</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> y=
</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> z </s=
pan><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> foo</s=
pan><span style=3D"color:#660">()</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#660">--</span><span style=3D"color:#606">Declares</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#066">3</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#008">local</span><sp=
an style=3D"color:#000"> variables</span><span style=3D"color:#660">,</span=
><span style=3D"color:#000"> initializing them </span><span style=3D"color:=
#008">with</span><span style=3D"color:#000"> </span><span style=3D"color:#0=
66">3</span><span style=3D"color:#000"> values </span><span style=3D"color:=
#008">from</span><span style=3D"color:#000"> the </span><span style=3D"colo=
r:#008">function</span><span style=3D"color:#660">.</span><span style=3D"co=
lor:#000"><br><br></span><span style=3D"color:#008">local</span><span style=
=3D"color:#000"> w </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"c=
olor:#000">foo</span><span style=3D"color:#660">()}</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#660">--</span><span style=3D"color:=
#606">Stores</span><span style=3D"color:#000"> the sequence of values retur=
ned </span><span style=3D"color:#008">from</span><span style=3D"color:#000"=
> </span><span style=3D"color:#080">`foo`</span><span style=3D"color:#000">=
</span><span style=3D"color:#008">in</span><span style=3D"color:#000"> a t=
able </span><span style=3D"color:#660">(</span><span style=3D"color:#000">a=
ka</span><span style=3D"color:#660">:</span><span style=3D"color:#000"> arr=
ay</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br>=
<br></span><span style=3D"color:#008">local</span><span style=3D"color:#000=
"> a </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"=
> bar</span><span style=3D"color:#660">()</span><span style=3D"color:#000">=
</span><span style=3D"color:#660">--</span><span style=3D"color:#606">Stor=
es</span><span style=3D"color:#000"> the table<br><br></span><span style=3D=
"color:#008">local</span><span style=3D"color:#000"> comp </span><span styl=
e=3D"color:#660">=3D</span><span style=3D"color:#000"> bar</span><span styl=
e=3D"color:#660">(</span><span style=3D"color:#000">foo</span><span style=
=3D"color:#660">())</span><span style=3D"color:#000"> </span><span style=3D=
"color:#660">--</span><span style=3D"color:#606">The</span><span style=3D"c=
olor:#000"> sequence </span><span style=3D"color:#008">is</span><span style=
=3D"color:#000"> passed to </span><span style=3D"color:#080">`bar`</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#008">as</span><span =
style=3D"color:#000"> </span><span style=3D"color:#066">3</span><span style=
=3D"color:#000"> parameters</span><span style=3D"color:#660">.</span><span =
style=3D"color:#000"><br><br></span><span style=3D"color:#008">local</span>=
<span style=3D"color:#000"> comp2 </span><span style=3D"color:#660">=3D</sp=
an><span style=3D"color:#000"> bar</span><span style=3D"color:#660">(</span=
><span style=3D"color:#000">bar</span><span style=3D"color:#660">())</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">--</span><spa=
n style=3D"color:#000">A single parameter </span><span style=3D"color:#008"=
>is</span><span style=3D"color:#000"> passed to the outer </span><span styl=
e=3D"color:#080">`bar`</span><span style=3D"color:#660">.</span><span style=
=3D"color:#000"><br><br></span><span style=3D"color:#008">local</span><span=
style=3D"color:#000"> comp3 </span><span style=3D"color:#660">=3D</span><s=
pan style=3D"color:#000"> bar</span><span style=3D"color:#660">(</span><spa=
n style=3D"color:#000">unpack</span><span style=3D"color:#660">(</span><spa=
n style=3D"color:#000">bar</span><span style=3D"color:#660">()))</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">--</span><span st=
yle=3D"color:#606">Unpacks</span><span style=3D"color:#000"> the array </sp=
an><span style=3D"color:#008">into</span><span style=3D"color:#000"> the ou=
ter </span><span style=3D"color:#080">`bar`'s parameters<br></span></div></=
code></div><br>I
find that much more reasonable and consistent than the Python syntax.=20
There is a distinction between a sequence of values and a data=20
structure. `foo` and `bar` may be "conceptually" the same, but=20
functionally they're different. One returns a sequence of values, the=20
other returns a table. If you need to convert a table into a sequence of
values, you call `unpack`. If you need to convert a sequence of values=20
into a table, you create a table with it.<br><br>Sequences of values in=20
Lua are ephemeral; if you want to store the sequence and preserve it as a
sequence, you stick it in a table. But if you just want to compose=20
functions, store values, and the like, you use the sequence as is.<br><br>I=
f
C++ is going to pattern its functionality off of something, I'd much=20
rather Lua's proper MRV syntax than Python's MRVs-as-arrays (I assume=20
the () syntax is creating an array of some kind).<br></div></div></blockquo=
te><div><br>We still need a special "unpacking" syntax to bind the multi re=
turn values to variables because the comma operator is already taken and no=
t sufficient for this task. The following looks very confusing and it doesn=
't even account for multiple return values of different types. It also does=
n't let us assign return values directly to pre-existing variables.<br><br>=
<div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); b=
order-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; wo=
rd-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subprettypr=
int"><span style=3D"color: #660;" class=3D"styled-by-prettify">[</span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">int</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">,</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">int</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">]</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> foo</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> bar</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">();</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color=
: #800;" class=3D"styled-by-prettify">//Initializes x, y, z using foo's ret=
urn values??</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">int<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> x</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> y</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> z </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> foo</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">();</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br></span><span style=3D"color: #800;" class=3D"styled-by-prettify">//=
Initializes only c using bar's() return value and leaves a and b uninitiali=
zed</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> a</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> b</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> c </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> bar</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&n=
bsp;</span></div></code></div><br>We could allow using auto here:<br><div c=
lass=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-=
color: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wra=
p: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><=
span style=3D"color: #660;" class=3D"styled-by-prettify">[</span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">long</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">,</span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">double</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">]</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> foo</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> x</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> y</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> z </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> foo</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #800;" class=3D"styled-by-prettify">//x is int, y i=
s long, z is double</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span></div></code></div><br>But this still doesn't allow us =
to specify cv and ref qualifiers for the individual variables.<br> </d=
iv><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br><=
/div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;=
border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div> </=
div><br><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><br><=
/div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;=
border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>As was s=
tated earlier, doing it this way would be a huge change that likely would n=
ever make it past the committee.</div></div></blockquote><div><br>But
it's the right way to do it. And quite frankly, we don't need multiple=20
return values so badly that we should do it the wrong way just to have <i>s=
ome</i> convenient way to do it.<br><br>Some
people use tuples a lot (some might say to the point of overuse). But=20
you shouldn't steal potentially useful syntax from those C++ programmers
who don't use them. </div></div></blockquote><div><br></div><div>Programme=
rs
who have no interest in tuple itself can just use the syntax to return=20
multiple values and unpack them at the call site. They don't have to=20
care that tuple (or something tuple like) is used to accomplish this.</div>=
</div></blockquote><div><br>Except that they have to pay the cost for it. C=
onsider something simple like this:<br><br><div style=3D"background-color:r=
gb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-wid=
th:1px;word-wrap:break-word"><code><div><span style=3D"color:#008">auto</sp=
an><span style=3D"color:#000"> single_value</span><span style=3D"color:#660=
">()</span><span style=3D"color:#000"><br></span><span style=3D"color:#660"=
>{</span><span style=3D"color:#000"><br> std</span><span style=3D"col=
or:#660">::</span><span style=3D"color:#008">string</span><span style=3D"co=
lor:#000"> a </span><span style=3D"color:#660">=3D</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">...;</span><span style=3D"color=
:#000"><br> </span><span style=3D"color:#008">return</span><span styl=
e=3D"color:#000"> a</span><span style=3D"color:#660">;</span><span style=3D=
"color:#000"><br></span><span style=3D"color:#660">}</span><span style=3D"c=
olor:#000"><br><br></span><span style=3D"color:#008">auto</span><span style=
=3D"color:#000"> multi_value</span><span style=3D"color:#660">()</span><spa=
n style=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span =
style=3D"color:#000"><br> std</span><span style=3D"color:#660">::</sp=
an><span style=3D"color:#008">string</span><span style=3D"color:#000"> a </=
span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">...;</span><span style=3D"color:#000"><br>&nbs=
p; std</span><span style=3D"color:#660">::</span><span style=3D"color:#000"=
>vector b </span><span style=3D"color:#660">=3D</span><span style=3D"color:=
#000"> </span><span style=3D"color:#660">...;</span><span style=3D"color:#0=
00"><br> </span><span style=3D"color:#008">return</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">[</span><span style=3D"c=
olor:#000">a</span><span style=3D"color:#660">;</span><span style=3D"color:=
#000"> b</span><span style=3D"color:#660">];</span><span style=3D"color:#00=
0"><br></span><span style=3D"color:#660">}</span></div></code></div><br>`si=
ngle_value`
is subject to copy elision, so you should feel no problem with using=20
it. Even with a small-string-optimized std::string class, you will get=20
the maximum possible performance if you're using the result to=20
initialize an object.<br><br>With language-level multiple return values,
`multi_value` would be able to operate under the same principle. `a`=20
and `b` would be considered return values, and they would each be=20
separately subject to elision.<br><br>With your way, that's just not=20
possible. If that syntax creates a `tuple`, then it must copy or move=20
initialize the elements of that `tuple`. So even though the `tuple`=20
itself is subject to elision, the creation of it is not.<br></div></div></b=
lockquote><div><br>So whats stopping someone from writing a proposal to all=
ow copy/move elision in your multi_value() example? Just because it can't h=
appen now doesn't mean we can't change the standard. Multi return values wo=
uld be a primary use case for such a proposal.<br><br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><div> </div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr"><div>Syntax is a precious commod=
ity, which once apportioned, cannot be taken back.<br><br>It
should also be noted that reflection, with the full ability to=20
compile-time inspect and generate types with full syntax=20
(including variable names) makes tuples... a dubious proposition for the
future of C++. With reflection, you can index a struct by number. With=20
reflection, you can take any typelist and build an honest-to-God=20
struct out of it (which can be standard layout and such).<br><br>In=20
short, it is entirely possible that tuples will become obsolete, thus=20
also obsoleting this kind of syntax. So let's not have another std::bind
happen here...<br></div></div></blockquote><div><br></div><div><div style=
=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;background-color=
:rgb(250,250,250)"><code><div><span style=3D"color:#660">[</span><span styl=
e=3D"color:#008">int</span><span style=3D"color:#660">,</span><span style=
=3D"color:#008">long</span><span style=3D"color:#660">,</span><span style=
=3D"color:#008">double</span><span style=3D"color:#660">]</span><span style=
=3D"color:#000"> foo</span><span style=3D"color:#660">();</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#008">auto</span><span styl=
e=3D"color:#000"> x </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> foo</span><span style=3D"color:#660">();</span></div></cod=
e></div><br></div><div>Ok, if tuple is out then what is decltype(x) in the =
above example doing things your way?</div></div></blockquote><div><br>There=
are two defensible answers to this:<br><br>1)
A compilation error. You called a function that returns 3 things, but=20
you only captured one. That suggests you weren't paying attention.<br><br>2=
) `int`. The other two types are dropped on the floor.<br><br>#2 is probabl=
y the way to go. Any sort of aggregate object type is not even up for discu=
ssion.<br></div></div></blockquote><div><br>Then I should also ask you how =
do you plan on capturing the multiple values? Using a syntax similar to the=
one I proposed?<br><br>This looks bad:<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 clas=
s=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #660;=
" class=3D"styled-by-prettify">[</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">int</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">,</span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">float</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">]</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> foo</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">[</span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> x</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> y</span><span style=3D"color: #660;" class=3D"styled-by-prettify">]</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </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"co=
lor: #660;" class=3D"styled-by-prettify">();</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" clas=
s=3D"styled-by-prettify">//Ok captures into x and y</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">[</span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> x</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">void</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">]</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> foo</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">();</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"st=
yled-by-prettify">//Ok captures first into x, throws away second</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> x </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> foo</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">();</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-pr=
ettify">//Captures only first??</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br></span></div></code></div><br>The last line there =
looks like an easy recipe for bugs, especially in generic code. I would sug=
gest making it a compiler error.<br><br>Also what if I want to save the seq=
uence so that I can forward it multiple times?<br>Using your approach, I mi=
ght suggest allowing auto... to capture all of the return values so that th=
ey can be forwarded along. This could work just like a variadic template pa=
rameter pack.<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: #008;" class=3D"styled-by-p=
rettify">void</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> foo</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">float</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">[</span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">int</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">float</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">]</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> bar</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">();</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br><br></span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">...</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> x </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> bar</span><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><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">x</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">...);</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br>foo</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify">x</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">...);</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span></div></code></div><br>But we still have the gen=
eric code problems that Miro brought up.<br> </div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br>Multiple return value=
s means <i>multiple return values</i>, not "pack multiple values into some =
kind of object and unpack them later".<br> </div><blockquote class=3D"=
gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid=
;padding-left:1ex"><div dir=3D"ltr"><div>
Another kind of typelist which is standard layout compatible? Or are we
no longer able to capture all of the return values into one object?</div><=
/div></blockquote><div><br>If you want to capture them all in an object, yo=
u just ask for it:<br><br><div style=3D"background-color:rgb(250,250,250);b=
order-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:=
break-word"><code><div><span style=3D"color:#008">auto</span><span style=3D=
"color:#000"> x </span><span style=3D"color:#660">=3D</span><span style=3D"=
color:#000"> make_tuple</span><span style=3D"color:#660">(</span><span styl=
e=3D"color:#000">foo</span><span style=3D"color:#660">());</span></div></co=
de></div><br>That
is neither hard nor particularly verbose. You can even stick them in an
array, if all of the returned values are of the same type:<br><br><div sty=
le=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);borde=
r-style:solid;border-width:1px;word-wrap:break-word"><code><div><span style=
=3D"color:#008">auto</span><span style=3D"color:#000"> x </span><span style=
=3D"color:#660">=3D</span><span style=3D"color:#000"> make_array</span><spa=
n style=3D"color:#660">(</span><span style=3D"color:#000">foo</span><span s=
tyle=3D"color:#660">());</span></div></code></div><br></div></div></blockqu=
ote><div><br>These require copy/move. In your example, unpacking is free (n=
o-op) and packing requires a copy/move. In my example unpacking is free (us=
ing references) and packing is also free, assuming you want to continue usi=
ng the pack type returned by the function. <br></div><div> </div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Or in an arbi=
trary data structure:<br><br><div style=3D"background-color:rgb(250,250,250=
);border-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wr=
ap:break-word"><code><div><span style=3D"color:#008">auto</span><span style=
=3D"color:#000"> x </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#000">vector</span><span style=3D"color:#660"><</span><span st=
yle=3D"color:#606">Type</span><span style=3D"color:#660">>{</span><span =
style=3D"color:#000">foo</span><span style=3D"color:#660">()};</span><span =
style=3D"color:#000"><br></span></div></code></div><br>But
most people using multiple return values don't capture them in a big=20
object, so we don't make the syntax optimal for that case.<br></div></div><=
/blockquote><div><br>Its not uncommon. Every class that has multiple "value=
s" (e.g unordered_map) will be returning them in a pack using its def=
ault iterators so that one can write a simple range for loop.<br> </di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></=
div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>If not us=
ing tuple, can you explain in a bit more detail how your proposed solution =
would actually work?</div></div></blockquote><div><br>The details of how it=
works are more or less the way Lua works.<br><br>In C++ parlance, the noti=
on of a "sequence of values" would be a construct. It would <i>not</i>
necessarily be an "expression", in the same way that a braced-init-list
is not an expression. Since it's a new construct, you can give it=20
whatever properties you want.<br><br>Functions can return sequences of=20
values, with the sequence as a full part of its return type. Using the=20
sequence initialization syntax, you can initialize/assign multiple=20
variables to a sequence of values. If a sequence of values is given to a
function argument list, the values are placed in that list as=20
arguments. If the sequence of values is used in any other kind of=20
expression, then it resolves down to the first element of that sequence=20
of values.<br><br>Initialization/assignment of variables through a sequence=
would work element by element, in order from left to right.<br></div></div=
></blockquote><div><br>I would suggest maybe piggybacking off of varadic te=
mplate parameter packs (If they can fit into this feature) instead of inven=
ting a yet another brand new thing which is only used for multiple return v=
alues which itself does not show up very often.<br><br>You mentioned reflec=
tion before. I believe with reflection, we can achieve even better interfac=
es if we designed this MRV feature around unpacking collections of objects.=
<br>For example, imagine if we could unpack a pod struct like this (impleme=
nted using reflection):<br><br><div class=3D"prettyprint" style=3D"backgrou=
nd-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-styl=
e: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyp=
rint"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">struct</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> kv </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">string=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> key</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> value</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">};</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br><br>kv kv</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">[<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> k</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> v</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">]</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> kv</sp=
an><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>Why is this so great? Here is an example:<br><br><div class=3D"p=
rettyprint" style=3D"background-color: rgb(250, 250, 250); border-color: rg=
b(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-=
word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">template</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">typename</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> K</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">typename</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> V</span><span style=3D"color: #660;" class=3D"styled-by-prettify">>=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">class</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">HashMap</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">public</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">struct</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> kv </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> K key</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> V value</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">};</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br> </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">class</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> iterator </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">public</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> s=
td</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">iterator</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">std</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify">bidirectional_iterator_tag</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">kv</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">></span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify=
">/* ... */</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">};</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> </spa=
n><span style=3D"color: #800;" class=3D"styled-by-prettify">//...</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br><br></span><span style=3D"colo=
r: #606;" class=3D"styled-by-prettify">HashMap</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> hashmap </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"s=
tyled-by-prettify">/* something */</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br><br></span><span style=3D"color: #800;" class=3D"styled-=
by-prettify">//Iterate using kv struct (more descriptive than pair)</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">for</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">&</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> kv</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> hashmap</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br> doSomethin=
g</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">kv</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">key</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> kv</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify">value</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><span=
style=3D"color: #800;" class=3D"styled-by-prettify">//Iterate by unpacking=
the kv struct first</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">for</span><span style=3D"color: #660;" class=3D"styled-by-prettify">([<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">&</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> key</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">auto</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">&</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> value</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">]:</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> hashmap</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"><br> doSomething=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">key</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> value</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br><br></span><span style=3D"color: #800;" class=3D"styled-=
by-prettify">//Iterate over only the keys</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">for</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">([</span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">auto</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">&</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
key</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">void</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">]:</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> hashmap</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">{}</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br><br></span><span style=3D"color: #800;" class=3D"styled-by-pret=
tify">//Iterate over only the values</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">for</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">([</span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">void</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">&</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> value</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">]:</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> hashmap</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">{}</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br></span></div></code></div><br>If the MRV feature is designed aro=
und unpacking collections of objects, then we can get interfaces like this =
for free from reflection. All 4 example loops are enabled without any addit=
ional work by the author of HashMap. <br><br>If MRV is designed using seque=
nces, then the class author has to provide separate iterators for returning=
an MRV sequence and also returning a pack in the default iterators. Class =
designers are already overburdened with boilerplate for writing type trait =
tags, iterator types, copy/move constructors, comparison operators, swap op=
erator, etc.. <br></div><br>The Lua way of doing things might be elegant, b=
ut lua is also a very simple language. It doesn't have the same features an=
d restrictions of C++ and I'm not sure yet if that approach would be the be=
st way.<br><br>On Wednesday, May 27, 2015 at 4:51:58 AM UTC-4, Miro Knejp w=
rote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:b=
reak-word">I assume Matthew=E2=80=99s point comes from dealing with templat=
e code.<div><br></div><div>template<class F></div><div>??? contrived_=
example(F f) {</div><div> return f();</div><div>}</div><div><b=
r></div><div>The author would probably expect that ??? can be plain =E2=80=
=9Cauto=E2=80=9D, implying =E2=80=9Cin some places auto can expand to multi=
ple types=E2=80=9D. Then there=E2=80=99s the point of what generic code wou=
ld require to do to consistently capture the return value(s) of a Callable =
without knowing if there are one or multiple return values.</div><div><br><=
/div><div>template<class F></div><div>void contrived_example2(F f) {<=
/div><div> ??? x =3D f();</div><div> ...</div><di=
v>}</div><div><br></div><div>Should ??? be something that can potentially c=
apture a single or multiple values depending on the initialization? If so w=
hat can be done with x down the pipeline? Or is a concept necessary to over=
load contrived_example2 for functions with single or multiple return values=
? Is template code forced into packing every Callable=E2=80=99s invocation =
into make_tuple() just in case it might return multiple values?</div><div><=
br></div></div></blockquote><div><br>These are very good questions. If mult=
i return is just sugar for returning a pack type, then generic code works j=
ust fine without any issue. If not, then we have a lot of questions to answ=
er. <br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
------=_Part_174_1468761672.1432739494049--
------=_Part_173_2103744840.1432739494049--
.
Author: Edward Catmur <ed@catmur.co.uk>
Date: Wed, 27 May 2015 08:25:15 -0700 (PDT)
Raw View
------=_Part_662_313433598.1432740315374
Content-Type: multipart/alternative;
boundary="----=_Part_663_101095495.1432740315374"
------=_Part_663_101095495.1432740315374
Content-Type: text/plain; charset=UTF-8
On Wednesday, 27 May 2015 16:11:34 UTC+1, Matthew Fioravante wrote:
>
> I would suggest maybe piggybacking off of varadic template parameter packs
> (If they can fit into this feature) instead of inventing a yet another
> brand new thing which is only used for multiple return values which itself
> does not show up very often.
>
> You mentioned reflection before. I believe with reflection, we can achieve
> even better interfaces if we designed this MRV feature around unpacking
> collections of objects.
> For example, imagine if we could unpack a pod struct like this
> (implemented using reflection):
>
> struct kv {
> string key;
> int value;
> };
>
> kv kv;
> [auto k; auto v] = kv;
>
> Why is this so great? Here is an example:
>
> template <typename K, typename V>
> class HashMap {
> public:
> struct kv { K key; V value; };
> class iterator : public std::iterator<std::bidirectional_iterator_tag,kv
> > { /* ... */ };
> //...
> };
>
> HashMap hashmap = /* something */;
>
> //Iterate using kv struct (more descriptive than pair)
> for(auto& kv: hashmap) {
> doSomething(kv.key, kv.value);
> }
>
> //Iterate by unpacking the kv struct first
> for([auto& key; auto& value]: hashmap) {
> doSomething(key, value);
> }
>
> //Iterate over only the keys
> for([auto& key; void]: hashmap) {}
>
> //Iterate over only the values
> for([void; auto& value]: hashmap) {}
>
> If the MRV feature is designed around unpacking collections of objects,
> then we can get interfaces like this for free from reflection. All 4
> example loops are enabled without any additional work by the author of
> HashMap.
>
> If MRV is designed using sequences, then the class author has to provide
> separate iterators for returning an MRV sequence and also returning a pack
> in the default iterators. Class designers are already overburdened with
> boilerplate for writing type trait tags, iterator types, copy/move
> constructors, comparison operators, swap operator, etc..
>
I really don't like the idea of having reflection invoked by a core
language feature; remember that reflection can (by design) bypass access
control. Instead, why not allow MRV to invoke a conversion function? It's
minimal boilerplate for the library author:
struct kv { K key; V value; operator[K, V] { return [key, value]; } };
MRV conversion functions could be added to pair and tuple in the library,
meaning there's no need to invoke reflection or privilege std::get<N>.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_663_101095495.1432740315374
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, 27 May 2015 16:11:34 UTC+1, Matthew Fioravan=
te wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><di=
v>I would suggest maybe piggybacking off of varadic template parameter pack=
s (If they can fit into this feature) instead of inventing a yet another br=
and new thing which is only used for multiple return values which itself do=
es not show up very often.<br></div><div><br>You mentioned reflection befor=
e. I believe with reflection, we can achieve even better interfaces if we d=
esigned this MRV feature around unpacking collections of objects.<br>For ex=
ample, imagine if we could unpack a pod struct like this (implemented using=
reflection):<br><br><div 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><div><span style=3D"color:#008">struct</span><span style=3D"co=
lor:#000"> kv </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br></span><span style=3D"color:#008">string</span><span style=3D"c=
olor:#000"> key</span><span style=3D"color:#660">;</span><span style=3D"col=
or:#000"><br></span><span style=3D"color:#008">int</span><span style=3D"col=
or:#000"> value</span><span style=3D"color:#660">;</span><span style=3D"col=
or:#000"><br></span><span style=3D"color:#660">};</span><span style=3D"colo=
r:#000"><br><br>kv kv</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">[</span><span style=
=3D"color:#008">auto</span><span style=3D"color:#000"> k</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#008">auto</span><span style=3D"color:#000"> v</span><span style=3D"co=
lor:#660">]</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660">=3D</span><span style=3D"color:#000"> kv</span><span style=3D"color:#6=
60">;</span><span style=3D"color:#000"><br></span></div></code></div><br>Wh=
y is this so great? Here is an example:<br><br><div style=3D"background-col=
or:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border=
-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#008">temp=
late</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&l=
t;</span><span style=3D"color:#008">typename</span><span style=3D"color:#00=
0"> K</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> =
</span><span style=3D"color:#008">typename</span><span style=3D"color:#000"=
> V</span><span style=3D"color:#660">></span><span style=3D"color:#000">=
<br></span><span style=3D"color:#008">class</span><span style=3D"color:#000=
"> </span><span style=3D"color:#606">HashMap</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">{</span><span style=3D"color:#000"><b=
r></span><span style=3D"color:#008">public</span><span style=3D"color:#660"=
>:</span><span style=3D"color:#000"><br> </span><span style=3D"color:=
#008">struct</span><span style=3D"color:#000"> kv </span><span style=3D"col=
or:#660">{</span><span style=3D"color:#000"> K key</span><span style=3D"col=
or:#660">;</span><span style=3D"color:#000"> V value</span><span style=3D"c=
olor:#660">;</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">};</span><span style=3D"color:#000"><br> </span><span style=3D"=
color:#008">class</span><span style=3D"color:#000"> iterator </span><span s=
tyle=3D"color:#660">:</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">public</span><span style=3D"color:#000"> std</span><span st=
yle=3D"color:#660">::</span><span style=3D"color:#000">iterator</span><span=
style=3D"color:#660"><</span><span style=3D"color:#000">std</span><span=
style=3D"color:#660">::</span><span style=3D"color:#000">bidirection<wbr>a=
l_iterator_tag</span><span style=3D"color:#660">,</span><span style=3D"colo=
r:#000">kv</span><span style=3D"color:#660">></span><span style=3D"color=
:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#000=
"> </span><span style=3D"color:#800">/* ... */</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">};</span><span style=3D"color:#000"=
><br> </span><span style=3D"color:#800">//...</span><span style=3D"co=
lor:#000"><br></span><span style=3D"color:#660">};</span><span style=3D"col=
or:#000"><br><br></span><span style=3D"color:#606">HashMap</span><span styl=
e=3D"color:#000"> hashmap </span><span style=3D"color:#660">=3D</span><span=
style=3D"color:#000"> </span><span style=3D"color:#800">/* something */</s=
pan><span style=3D"color:#660">;</span><span style=3D"color:#000"><br><br><=
/span><span style=3D"color:#800">//Iterate using kv struct (more descriptiv=
e than pair)</span><span style=3D"color:#000"><br></span><span style=3D"col=
or:#008">for</span><span style=3D"color:#660">(</span><span style=3D"color:=
#008">auto</span><span style=3D"color:#660">&</span><span style=3D"colo=
r:#000"> kv</span><span style=3D"color:#660">:</span><span style=3D"color:#=
000"> hashmap</span><span style=3D"color:#660">)</span><span style=3D"color=
:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#000=
"><br> doSomething</span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#000">kv</span><span style=3D"color:#660">.</span><span style=
=3D"color:#000">key</span><span style=3D"color:#660">,</span><span style=3D=
"color:#000"> kv</span><span style=3D"color:#660">.</span><span style=3D"co=
lor:#000">value</span><span style=3D"color:#660">);</span><span style=3D"co=
lor:#000"><br></span><span style=3D"color:#660">}</span><span style=3D"colo=
r:#000"><br><br></span><span style=3D"color:#800">//Iterate by unpacking th=
e kv struct first</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">for</span><span style=3D"color:#660">([</span><span style=
=3D"color:#008">auto</span><span style=3D"color:#660">&</span><span sty=
le=3D"color:#000"> key</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">auto</span><span style=
=3D"color:#660">&</span><span style=3D"color:#000"> value</span><span s=
tyle=3D"color:#660">]:</span><span style=3D"color:#000"> hashmap</span><spa=
n style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660">{</span><span style=3D"color:#000"><br> doSomething=
</span><span style=3D"color:#660">(</span><span style=3D"color:#000">key</s=
pan><span style=3D"color:#660">,</span><span style=3D"color:#000"> value</s=
pan><span style=3D"color:#660">);</span><span style=3D"color:#000"><br></sp=
an><span style=3D"color:#660">}</span><span style=3D"color:#000"><br><br></=
span><span style=3D"color:#800">//Iterate over only the keys</span><span st=
yle=3D"color:#000"><br></span><span style=3D"color:#008">for</span><span st=
yle=3D"color:#660">([</span><span style=3D"color:#008">auto</span><span sty=
le=3D"color:#660">&</span><span style=3D"color:#000"> key</span><span s=
tyle=3D"color:#660">;</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">void</span><span style=3D"color:#660">]:</span><span style=
=3D"color:#000"> hashmap</span><span style=3D"color:#660">)</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span style=
=3D"color:#000"><br><br></span><span style=3D"color:#800">//Iterate over on=
ly the values</span><span style=3D"color:#000"><br></span><span style=3D"co=
lor:#008">for</span><span style=3D"color:#660">([</span><span style=3D"colo=
r:#008">void</span><span style=3D"color:#660">;</span><span style=3D"color:=
#000"> </span><span style=3D"color:#008">auto</span><span style=3D"color:#6=
60">&</span><span style=3D"color:#000"> value</span><span style=3D"colo=
r:#660">]:</span><span style=3D"color:#000"> hashmap</span><span style=3D"c=
olor:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">{}</span><span style=3D"color:#000"><br></span></div></code></div><br=
>If the MRV feature is designed around unpacking collections of objects, th=
en we can get interfaces like this for free from reflection. All 4 example =
loops are enabled without any additional work by the author of HashMap. <br=
><br>If MRV is designed using sequences, then the class author has to provi=
de separate iterators for returning an MRV sequence and also returning a pa=
ck in the default iterators. Class designers are already overburdened with =
boilerplate for writing type trait tags, iterator types, copy/move construc=
tors, comparison operators, swap operator, etc.. </div></div></blockqu=
ote><div><br></div><div>I really don't like the idea of having reflection i=
nvoked by a core language feature; remember that reflection can (by design)=
bypass access control. Instead, why not allow MRV to invoke a conversion f=
unction? It's minimal boilerplate for the library author:</div><div><br></d=
iv><div><span style=3D"font-family: monospace; color: rgb(0, 0, 0); backgro=
und-color: rgb(250, 250, 250);"> </span><span style=3D"font-fami=
ly: monospace; color: rgb(0, 0, 136); background-color: rgb(250, 250, 250);=
">struct</span><span style=3D"font-family: monospace; color: rgb(0, 0, 0); =
background-color: rgb(250, 250, 250);"> kv </span><span style=3D"=
font-family: monospace; color: rgb(102, 102, 0); background-color: rgb(250,=
250, 250);">{</span><span style=3D"font-family: monospace; color: rgb(0, 0=
, 0); background-color: rgb(250, 250, 250);"> K key</span><span style=
=3D"font-family: monospace; color: rgb(102, 102, 0); background-color: rgb(=
250, 250, 250);">;</span><span style=3D"font-family: monospace; color: rgb(=
0, 0, 0); background-color: rgb(250, 250, 250);"> V value</span><span =
style=3D"font-family: monospace; color: rgb(102, 102, 0); background-color:=
rgb(250, 250, 250);">;</span><span style=3D"font-family: monospace; color:=
rgb(0, 0, 0); background-color: rgb(250, 250, 250);"> operator[K, V] =
{ return [key, value]; } </span><span style=3D"font-family: monospace;=
color: rgb(102, 102, 0); background-color: rgb(250, 250, 250);">};</span><=
span style=3D"font-family: monospace; color: rgb(0, 0, 0); background-color=
: rgb(250, 250, 250);"><br></span></div><div><font face=3D"arial, sans-seri=
f" size=3D"2" color=3D"#000000" style=3D"background-color: rgb(255, 255, 25=
5);"><br></font></div><div><font face=3D"arial, sans-serif" size=3D"2" colo=
r=3D"#000000" style=3D"background-color: rgb(255, 255, 255);">MRV conversio=
n functions could be added to pair and tuple in the library, meaning there'=
s no need to invoke reflection or privilege std::get<N>.</font></div>=
</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
------=_Part_663_101095495.1432740315374--
------=_Part_662_313433598.1432740315374--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 27 May 2015 08:33:02 -0700
Raw View
On Wednesday 27 May 2015 11:21:47 Matthew Woehlke wrote:
> In Python, "return x, y" is syntactic sugar for "return (x, y)". I
> suppose we could allow similar sugar in C++, possibly with the
> requirement that the function was declared with the tuple sugar (as in
> the declarations in the above example) in order to avoid changing the
> meaning of existing code w.r.t. 'operator,'.
Please don't, because operator, can be overloaded. Using it is one of the
tricks to handling void returns.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Matthew Fioravante <fmatthew5876@gmail.com>
Date: Wed, 27 May 2015 08:34:00 -0700 (PDT)
Raw View
------=_Part_244_764112919.1432740840035
Content-Type: multipart/alternative;
boundary="----=_Part_245_551642050.1432740840041"
------=_Part_245_551642050.1432740840041
Content-Type: text/plain; charset=UTF-8
On Wednesday, May 27, 2015 at 11:25:15 AM UTC-4, Edward Catmur wrote:
>
> On Wednesday, 27 May 2015 16:11:34 UTC+1, Matthew Fioravante wrote:
>>
>> I would suggest maybe piggybacking off of varadic template parameter
>> packs (If they can fit into this feature) instead of inventing a yet
>> another brand new thing which is only used for multiple return values which
>> itself does not show up very often.
>>
>> You mentioned reflection before. I believe with reflection, we can
>> achieve even better interfaces if we designed this MRV feature around
>> unpacking collections of objects.
>> For example, imagine if we could unpack a pod struct like this
>> (implemented using reflection):
>>
>> struct kv {
>> string key;
>> int value;
>> };
>>
>> kv kv;
>> [auto k; auto v] = kv;
>>
>> Why is this so great? Here is an example:
>>
>> template <typename K, typename V>
>> class HashMap {
>> public:
>> struct kv { K key; V value; };
>> class iterator : public std::iterator<std::bidirectional_iterator_tag,
>> kv> { /* ... */ };
>> //...
>> };
>>
>> HashMap hashmap = /* something */;
>>
>> //Iterate using kv struct (more descriptive than pair)
>> for(auto& kv: hashmap) {
>> doSomething(kv.key, kv.value);
>> }
>>
>> //Iterate by unpacking the kv struct first
>> for([auto& key; auto& value]: hashmap) {
>> doSomething(key, value);
>> }
>>
>> //Iterate over only the keys
>> for([auto& key; void]: hashmap) {}
>>
>> //Iterate over only the values
>> for([void; auto& value]: hashmap) {}
>>
>> If the MRV feature is designed around unpacking collections of objects,
>> then we can get interfaces like this for free from reflection. All 4
>> example loops are enabled without any additional work by the author of
>> HashMap.
>>
>> If MRV is designed using sequences, then the class author has to provide
>> separate iterators for returning an MRV sequence and also returning a pack
>> in the default iterators. Class designers are already overburdened with
>> boilerplate for writing type trait tags, iterator types, copy/move
>> constructors, comparison operators, swap operator, etc..
>>
>
> I really don't like the idea of having reflection invoked by a core
> language feature; remember that reflection can (by design) bypass access
> control.
>
That's why I suggested it working by default for only POD structs which are
all public and standard layout where compiler generating unpacking makes
sense without surprises.
> Instead, why not allow MRV to invoke a conversion function? It's minimal
> boilerplate for the library author:
>
> struct kv { K key; V value; operator[K, V] { return [key, value]; } };
>
> MRV conversion functions could be added to pair and tuple in the library,
> meaning there's no need to invoke reflection or privilege std::get<N>.
>
Sure, and this could be how one adds support for unpacking to any arbitrary
type and its much easier than implementing std::get. One has to be careful
with copies however.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_245_551642050.1432740840041
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, May 27, 2015 at 11:25:15 AM UTC-4, E=
dward Catmur wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr">On Wednesday, 27 May 2015 16:11:34 UTC+1, Matthew Fioravante wrote:<=
blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border=
-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>I would sugges=
t maybe piggybacking off of varadic template parameter packs (If they can f=
it into this feature) instead of inventing a yet another brand new thing wh=
ich is only used for multiple return values which itself does not show up v=
ery often.<br></div><div><br>You mentioned reflection before. I believe wit=
h reflection, we can achieve even better interfaces if we designed this MRV=
feature around unpacking collections of objects.<br>For example, imagine i=
f we could unpack a pod struct like this (implemented using reflection):<br=
><br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,1=
87,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><di=
v><span style=3D"color:#008">struct</span><span style=3D"color:#000"> kv </=
span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br></sp=
an><span style=3D"color:#008">string</span><span style=3D"color:#000"> key<=
/span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br></s=
pan><span style=3D"color:#008">int</span><span style=3D"color:#000"> value<=
/span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br></s=
pan><span style=3D"color:#660">};</span><span style=3D"color:#000"><br><br>=
kv kv</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><=
br></span><span style=3D"color:#660">[</span><span style=3D"color:#008">aut=
o</span><span style=3D"color:#000"> k</span><span style=3D"color:#660">;</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#008">auto</spa=
n><span style=3D"color:#000"> v</span><span style=3D"color:#660">]</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">=3D</span><span=
style=3D"color:#000"> kv</span><span style=3D"color:#660">;</span><span st=
yle=3D"color:#000"><br></span></div></code></div><br>Why is this so great? =
Here is an example:<br><br><div 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><div><span style=3D"color:#008">template</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#660"><</span><span style=
=3D"color:#008">typename</span><span style=3D"color:#000"> K</span><span st=
yle=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">typename</span><span style=3D"color:#000"> V</span><span st=
yle=3D"color:#660">></span><span style=3D"color:#000"><br></span><span s=
tyle=3D"color:#008">class</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#606">HashMap</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">{</span><span style=3D"color:#000"><br></span><span sty=
le=3D"color:#008">public</span><span style=3D"color:#660">:</span><span sty=
le=3D"color:#000"><br> </span><span style=3D"color:#008">struct</span=
><span style=3D"color:#000"> kv </span><span style=3D"color:#660">{</span><=
span style=3D"color:#000"> K key</span><span style=3D"color:#660">;</span><=
span style=3D"color:#000"> V value</span><span style=3D"color:#660">;</span=
><span style=3D"color:#000"> </span><span style=3D"color:#660">};</span><sp=
an style=3D"color:#000"><br> </span><span style=3D"color:#008">class<=
/span><span style=3D"color:#000"> iterator </span><span style=3D"color:#660=
">:</span><span style=3D"color:#000"> </span><span style=3D"color:#008">pub=
lic</span><span style=3D"color:#000"> std</span><span style=3D"color:#660">=
::</span><span style=3D"color:#000">iterator</span><span style=3D"color:#66=
0"><</span><span style=3D"color:#000">std</span><span style=3D"color:#66=
0">::</span><span style=3D"color:#000">bidirection<wbr>al_iterator_tag</spa=
n><span style=3D"color:#660">,</span><span style=3D"color:#000">kv</span><s=
pan style=3D"color:#660">></span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#660">{</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#800">/* ... */</span><span style=3D"color:#000"> </span><span =
style=3D"color:#660">};</span><span style=3D"color:#000"><br> </span>=
<span style=3D"color:#800">//...</span><span style=3D"color:#000"><br></spa=
n><span style=3D"color:#660">};</span><span style=3D"color:#000"><br><br></=
span><span style=3D"color:#606">HashMap</span><span style=3D"color:#000"> h=
ashmap </span><span style=3D"color:#660">=3D</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#800">/* something */</span><span style=3D"=
color:#660">;</span><span style=3D"color:#000"><br><br></span><span style=
=3D"color:#800">//Iterate using kv struct (more descriptive than pair)</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#008">for</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#008">auto</span>=
<span style=3D"color:#660">&</span><span style=3D"color:#000"> kv</span=
><span style=3D"color:#660">:</span><span style=3D"color:#000"> hashmap</sp=
an><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#660">{</span><span style=3D"color:#000"><br> doSo=
mething</span><span style=3D"color:#660">(</span><span style=3D"color:#000"=
>kv</span><span style=3D"color:#660">.</span><span style=3D"color:#000">key=
</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> kv</s=
pan><span style=3D"color:#660">.</span><span style=3D"color:#000">value</sp=
an><span style=3D"color:#660">);</span><span style=3D"color:#000"><br></spa=
n><span style=3D"color:#660">}</span><span style=3D"color:#000"><br><br></s=
pan><span style=3D"color:#800">//Iterate by unpacking the kv struct first</=
span><span style=3D"color:#000"><br></span><span style=3D"color:#008">for</=
span><span style=3D"color:#660">([</span><span style=3D"color:#008">auto</s=
pan><span style=3D"color:#660">&</span><span style=3D"color:#000"> key<=
/span><span style=3D"color:#660">;</span><span style=3D"color:#000"> </span=
><span style=3D"color:#008">auto</span><span style=3D"color:#660">&</sp=
an><span style=3D"color:#000"> value</span><span style=3D"color:#660">]:</s=
pan><span style=3D"color:#000"> hashmap</span><span style=3D"color:#660">)<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</span=
><span style=3D"color:#000"><br> doSomething</span><span style=3D"col=
or:#660">(</span><span style=3D"color:#000">key</span><span style=3D"color:=
#660">,</span><span style=3D"color:#000"> value</span><span style=3D"color:=
#660">);</span><span style=3D"color:#000"><br></span><span style=3D"color:#=
660">}</span><span style=3D"color:#000"><br><br></span><span style=3D"color=
:#800">//Iterate over only the keys</span><span style=3D"color:#000"><br></=
span><span style=3D"color:#008">for</span><span style=3D"color:#660">([</sp=
an><span style=3D"color:#008">auto</span><span style=3D"color:#660">&</=
span><span style=3D"color:#000"> key</span><span style=3D"color:#660">;</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#008">void</span=
><span style=3D"color:#660">]:</span><span style=3D"color:#000"> hashmap</s=
pan><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><=
span style=3D"color:#660">{}</span><span style=3D"color:#000"><br><br></spa=
n><span style=3D"color:#800">//Iterate over only the values</span><span sty=
le=3D"color:#000"><br></span><span style=3D"color:#008">for</span><span sty=
le=3D"color:#660">([</span><span style=3D"color:#008">void</span><span styl=
e=3D"color:#660">;</span><span style=3D"color:#000"> </span><span style=3D"=
color:#008">auto</span><span style=3D"color:#660">&</span><span style=
=3D"color:#000"> value</span><span style=3D"color:#660">]:</span><span styl=
e=3D"color:#000"> hashmap</span><span style=3D"color:#660">)</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span style=
=3D"color:#000"><br></span></div></code></div><br>If the MRV feature is des=
igned around unpacking collections of objects, then we can get interfaces l=
ike this for free from reflection. All 4 example loops are enabled without =
any additional work by the author of HashMap. <br><br>If MRV is designed us=
ing sequences, then the class author has to provide separate iterators for =
returning an MRV sequence and also returning a pack in the default iterator=
s. Class designers are already overburdened with boilerplate for writing ty=
pe trait tags, iterator types, copy/move constructors, comparison operators=
, swap operator, etc.. </div></div></blockquote><div><br></div><div>I =
really don't like the idea of having reflection invoked by a core language =
feature; remember that reflection can (by design) bypass access control.</d=
iv></div></blockquote><div><br>That's why I suggested it working by default=
for only POD structs which are all public and standard layout where compil=
er generating unpacking makes sense without surprises.<br> </div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div> Instead, why=
not allow MRV to invoke a conversion function? It's minimal boilerplate fo=
r the library author:</div><div><br></div><div><span style=3D"font-family:m=
onospace;color:rgb(0,0,0);background-color:rgb(250,250,250)"> </=
span><span style=3D"font-family:monospace;color:rgb(0,0,136);background-col=
or:rgb(250,250,250)">struct</span><span style=3D"font-family:monospace;colo=
r:rgb(0,0,0);background-color:rgb(250,250,250)"> kv </span><span =
style=3D"font-family:monospace;color:rgb(102,102,0);background-color:rgb(25=
0,250,250)">{</span><span style=3D"font-family:monospace;color:rgb(0,0,0);b=
ackground-color:rgb(250,250,250)"> K key</span><span style=3D"font-fam=
ily:monospace;color:rgb(102,102,0);background-color:rgb(250,250,250)">;</sp=
an><span style=3D"font-family:monospace;color:rgb(0,0,0);background-color:r=
gb(250,250,250)"> V value</span><span style=3D"font-family:monospace;c=
olor:rgb(102,102,0);background-color:rgb(250,250,250)">;</span><span style=
=3D"font-family:monospace;color:rgb(0,0,0);background-color:rgb(250,250,250=
)"> operator[K, V] { return [key, value]; } </span><span style=3D=
"font-family:monospace;color:rgb(102,102,0);background-color:rgb(250,250,25=
0)">};</span><span style=3D"font-family:monospace;color:rgb(0,0,0);backgrou=
nd-color:rgb(250,250,250)"><br></span></div><div><font style=3D"background-=
color:rgb(255,255,255)" size=3D"2" color=3D"#000000" face=3D"arial, sans-se=
rif"><br></font></div><div><font style=3D"background-color:rgb(255,255,255)=
" size=3D"2" color=3D"#000000" face=3D"arial, sans-serif">MRV conversion fu=
nctions could be added to pair and tuple in the library, meaning there's no=
need to invoke reflection or privilege std::get<N>.</font></div></di=
v></blockquote><div><br>Sure, and this could be how one adds support for un=
packing to any arbitrary type and its much easier than implementing std::ge=
t. One has to be careful with copies however.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
------=_Part_245_551642050.1432740840041--
------=_Part_244_764112919.1432740840035--
.
Author: Matthew Fioravante <fmatthew5876@gmail.com>
Date: Wed, 27 May 2015 08:43:36 -0700 (PDT)
Raw View
------=_Part_697_998400250.1432741416345
Content-Type: multipart/alternative;
boundary="----=_Part_698_1823267739.1432741416345"
------=_Part_698_1823267739.1432741416345
Content-Type: text/plain; charset=UTF-8
On Wednesday, May 27, 2015 at 11:33:06 AM UTC-4, Thiago Macieira wrote:
>
> On Wednesday 27 May 2015 11:21:47 Matthew Woehlke wrote:
> > In Python, "return x, y" is syntactic sugar for "return (x, y)". I
> > suppose we could allow similar sugar in C++, possibly with the
> > requirement that the function was declared with the tuple sugar (as in
> > the declarations in the above example) in order to avoid changing the
> > meaning of existing code w.r.t. 'operator,'.
>
> Please don't, because operator, can be overloaded. Using it is one of the
> tricks to handling void returns.
>
>
I'm happy with just using good old braced initialization, or other forms of
initialization that already exist if you so choose.
[int,float] foo() { return { 1, 2.0f }; }
[int,float] bar() { return [int,float](1, 2.0f); }
There's nothing ambiguous or overly verbose about that and it doesn't ask
the standard to invent more rules and syntax. I don't need additional sugar
to avoid typing {}. If MRV is implemented using a packed type, this syntax
is natural because we are constructing the pack object to be returned.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_698_1823267739.1432741416345
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, May 27, 2015 at 11:33:06 AM UTC-4, T=
hiago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Wednes=
day 27 May 2015 11:21:47 Matthew Woehlke wrote:
<br>> In Python, "return x, y" is syntactic sugar for "return (x, y)". I
<br>> suppose we could allow similar sugar in C++, possibly with the
<br>> requirement that the function was declared with the tuple sugar (a=
s in
<br>> the declarations in the above example) in order to avoid changing =
the
<br>> meaning of existing code w.r.t. 'operator,'.
<br>
<br>Please don't, because operator, can be overloaded. Using it is one of t=
he=20
<br>tricks to handling void returns.
<br><br></blockquote><div><br>I'm happy with just using good old braced ini=
tialization, or other forms of initialization that already exist if you so =
choose.<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(25=
0, 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-prettif=
y">[</span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span=
style=3D"color: #008;" class=3D"styled-by-prettify">float</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">]</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> foo</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">re=
turn</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #066;" class=3D"styled-by-prettify">1</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"style=
d-by-prettify">2.0f</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">[</span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">int</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">,</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">float</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">]</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> bar</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">[</span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">int</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">,</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
float</span><span style=3D"color: #660;" class=3D"styled-by-prettify">](</s=
pan><span style=3D"color: #066;" class=3D"styled-by-prettify">1</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
066;" class=3D"styled-by-prettify">2.0f</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br></span></div></code></div><br>There's nothing ambiguous or overly ve=
rbose about that and it doesn't ask the standard to invent more rules and s=
yntax. I don't need additional sugar to avoid typing {}. If MRV is implemen=
ted using a packed type, this syntax is natural because we are constructing=
the pack object to be returned.<br><br><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
------=_Part_698_1823267739.1432741416345--
------=_Part_697_998400250.1432741416345--
.
Author: Miro Knejp <miro.knejp@gmail.com>
Date: Wed, 27 May 2015 17:55:16 +0200
Raw View
--Apple-Mail=_58C5AA6B-57FB-49B2-8D4C-537D51A3440E
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 27 May 2015, at 17:11 , Nicol Bolas <jmckesson@gmail.com> wrote:
>=20
>=20
>=20
> On Wednesday, May 27, 2015 at 4:51:58 AM UTC-4, Miro Knejp wrote:
>=20
>> On 27 May 2015, at 09:43 , Nicol Bolas <jmck...@gmail.com <javascript:>>=
wrote:
>>=20
>>=20
>> [int,long,double] foo();
>> auto x =3D foo();
>>=20
>> Ok, if tuple is out then what is decltype(x) in the above example doing =
things your way?
>>=20
>> There are two defensible answers to this:
>>=20
>> 1) A compilation error. You called a function that returns 3 things, but=
you only captured one. That suggests you weren't paying attention.
>>=20
>> 2) `int`. The other two types are dropped on the floor.
>>=20
>> #2 is probably the way to go. Any sort of aggregate object type is not e=
ven up for discussion.
>>=20
>> Multiple return values means multiple return values, not "pack multiple =
values into some kind of object and unpack them later".
>> =20
>> Another kind of typelist which is standard layout compatible? Or are we =
no longer able to capture all of the return values into one object?
>>=20
>> If you want to capture them all in an object, you just ask for it:
>>=20
>> auto x =3D make_tuple(foo());
>>=20
>> That is neither hard nor particularly verbose. You can even stick them i=
n an array, if all of the returned values are of the same type:
>>=20
>> auto x =3D make_array(foo());
>>=20
>> Or in an arbitrary data structure:
>>=20
>> auto x =3D std::vector<Type>{foo()};
>>=20
>> But most people using multiple return values don't capture them in a big=
object, so we don't make the syntax optimal for that case.
>>=20
>=20
>=20
> I assume Matthew=E2=80=99s point comes from dealing with template code.
>=20
> template<class F>
> ??? contrived_example(F f) {
> return f();
> }
>=20
> The author would probably expect that ??? can be plain =E2=80=9Cauto=E2=
=80=9D, implying =E2=80=9Cin some places auto can expand to multiple types=
=E2=80=9D.
>=20
> Well, `auto` as a "return type" means something very different from `auto=
` as a variable declaration. So it's perfectly reasonable for `auto` or `de=
cltype(auto)` to deduce multiple return values. Just as it can deduce `void=
` (ie: zero return values).
> =20
> Then there=E2=80=99s the point of what generic code would require to do t=
o consistently capture the return value(s) of a Callable without knowing if=
there are one or multiple return values.
>=20
> template<class F>
> void contrived_example2(F f) {
> ??? x =3D f();
> ...
> }
>=20
> That one's easy. Since you're in generic code and could be getting multip=
le values, the only way to manipulate them is with a tuple. So that's what =
you stick them in:
>=20
> auto x =3D make_tuple(f());
>=20
My point was specifically that the author of the template function doesn=E2=
=80=99t necessarily know whether f has multiple return values without type_=
traiting the hell out of it. I understand this would require basically almo=
st every template function in existence with Callables to wrap every invoca=
tion in make_tuple(), just in case. Unless it is suggested to use concept s=
henanigans to overload the template function with concepts for all combinat=
ions of MRV/SRV Callable types accepted by the template function. Seems a b=
it excessive.
--=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/.
--Apple-Mail=_58C5AA6B-57FB-49B2-8D4C-537D51A3440E
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 27 May 2015, at 1=
7:11 , Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.com" class=3D"">jm=
ckesson@gmail.com</a>> wrote:</div><br class=3D"Apple-interchange-newlin=
e"><div class=3D""><div dir=3D"ltr" class=3D""><br class=3D""><br class=3D"=
">On Wednesday, May 27, 2015 at 4:51:58 AM UTC-4, Miro Knejp wrote:<blockqu=
ote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left=
: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word" cl=
ass=3D""><br class=3D""><div class=3D""><blockquote type=3D"cite" class=3D"=
"><div class=3D"">On 27 May 2015, at 09:43 , Nicol Bolas <<a href=3D"jav=
ascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"ZhKGsYWWzngJ" rel=3D"n=
ofollow" onmousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"=
this.href=3D'javascript:';return true;" class=3D"">jmck...@gmail.com</a>>=
; wrote:</div><br class=3D""><div class=3D""><div dir=3D"ltr" style=3D"font=
-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font=
-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;te=
xt-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" clas=
s=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;=
border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:=
solid;padding-left:1ex"><div dir=3D"ltr" class=3D""><div class=3D""><br cla=
ss=3D""></div><div class=3D""><div style=3D"border:1px solid rgb(187,187,18=
7);word-wrap:break-word;background-color:rgb(250,250,250)" class=3D""><code=
class=3D""><span style=3D"color:rgb(102,102,0)" class=3D"">[</span><span s=
tyle=3D"color:rgb(0,0,136)" class=3D"">int</span><span style=3D"color:rgb(1=
02,102,0)" class=3D"">,</span><span style=3D"color:rgb(0,0,136)" class=3D""=
>long</span><span style=3D"color:rgb(102,102,0)" class=3D"">,</span><span s=
tyle=3D"color:rgb(0,0,136)" class=3D"">double</span><span style=3D"color:rg=
b(102,102,0)" class=3D"">]</span><span class=3D""> </span>foo<span sty=
le=3D"color:rgb(102,102,0)" class=3D"">();</span><br class=3D""><span style=
=3D"color:rgb(0,0,136)" class=3D"">auto</span><span class=3D""><span class=
=3D""> </span>x<span class=3D""> </span></span><span style=3D"col=
or:rgb(102,102,0)" class=3D"">=3D</span><span class=3D""> </span>foo<s=
pan style=3D"color:rgb(102,102,0)" class=3D"">();</span><font color=3D"#666=
600" class=3D""></font></code></div><br class=3D""></div><div class=3D"">Ok=
, if tuple is out then what is decltype(x) in the above example doing thing=
s your way?</div></div></blockquote><div class=3D""><br class=3D"">There ar=
e two defensible answers to this:<br class=3D""><br class=3D"">1) A compila=
tion error. You called a function that returns 3 things, but you only captu=
red one. That suggests you weren't paying attention.<br class=3D""><br clas=
s=3D"">2) `int`. The other two types are dropped on the floor.<br class=3D"=
"><br class=3D"">#2 is probably the way to go. Any sort of aggregate object=
type is not even up for discussion.<br class=3D""><br class=3D"">Multiple =
return values means<span class=3D""> </span><i class=3D"">multiple ret=
urn values</i>, not "pack multiple values into some kind of object and unpa=
ck them later".<br class=3D""> </div><blockquote class=3D"gmail_quote"=
style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:=
rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"=
class=3D""><div class=3D"">Another kind of typelist which is standard layo=
ut compatible? Or are we no longer able to capture all of the return values=
into one object?</div></div></blockquote><div class=3D""><br class=3D"">If=
you want to capture them all in an object, you just ask for it:<br class=
=3D""><br class=3D""><div style=3D"background-color:rgb(250,250,250);border=
:1px solid rgb(187,187,187);word-wrap:break-word" class=3D""><code class=3D=
""><span style=3D"color:rgb(0,0,136)" class=3D"">auto</span><span class=3D"=
"><span class=3D""> </span>x<span class=3D""> </span></span><span=
style=3D"color:rgb(102,102,0)" class=3D"">=3D</span><span class=3D""> =
;</span>make_tuple<span style=3D"color:rgb(102,102,0)" class=3D"">(</span>f=
oo<span style=3D"color:rgb(102,102,0)" class=3D"">());</span></code></div><=
br class=3D"">That is neither hard nor particularly verbose. You can even s=
tick them in an array, if all of the returned values are of the same type:<=
br class=3D""><br class=3D""><div style=3D"background-color:rgb(250,250,250=
);border:1px solid rgb(187,187,187);word-wrap:break-word" class=3D""><code =
class=3D""><span style=3D"color:rgb(0,0,136)" class=3D"">auto</span><span c=
lass=3D""><span class=3D""> </span>x<span class=3D""> </span></sp=
an><span style=3D"color:rgb(102,102,0)" class=3D"">=3D</span><span class=3D=
""> </span>make_array<span style=3D"color:rgb(102,102,0)" class=3D"">(=
</span>foo<span style=3D"color:rgb(102,102,0)" class=3D"">());</span></code=
></div><br class=3D"">Or in an arbitrary data structure:<br class=3D""><br =
class=3D""><div style=3D"background-color:rgb(250,250,250);border:1px solid=
rgb(187,187,187);word-wrap:break-word" class=3D""><code class=3D""><span s=
tyle=3D"color:rgb(0,0,136)" class=3D"">auto</span><span class=3D""><span cl=
ass=3D""> </span>x<span class=3D""> </span></span><span style=3D"=
color:rgb(102,102,0)" class=3D"">=3D</span><span class=3D""> </span>st=
d<span style=3D"color:rgb(102,102,0)" class=3D"">::</span>vector<span style=
=3D"color:rgb(102,102,0)" class=3D""><</span><span style=3D"color:rgb(10=
2,0,102)" class=3D"">Type</span><span style=3D"color:rgb(102,102,0)" class=
=3D"">>{</span>foo<span style=3D"color:rgb(102,102,0)" class=3D""><wbr c=
lass=3D"">()};</span><br class=3D""></code></div><br class=3D"">But most pe=
ople using multiple return values don't capture them in a big object, so we=
don't make the syntax optimal for that case.<br class=3D""><br class=3D"">=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr" class=3D""><div class=3D""></div></=
div></blockquote></div></div></blockquote></div><div class=3D""><br class=
=3D""></div>I assume Matthew=E2=80=99s point comes from dealing with templa=
te code.<div class=3D""><br class=3D""></div><div class=3D"">template<cl=
ass F></div><div class=3D"">??? contrived_example(F f) {</div><div class=
=3D""> return f();</div><div class=3D"">}</div><div class=3D""=
><br class=3D""></div><div class=3D"">The author would probably expect that=
??? can be plain =E2=80=9Cauto=E2=80=9D, implying =E2=80=9Cin some places =
auto can expand to multiple types=E2=80=9D.</div></div></blockquote><div cl=
ass=3D""><br class=3D"">Well, `auto` as a "return type" means something ver=
y different from `auto` as a variable declaration. So it's perfectly reason=
able for `auto` or `decltype(auto)` to deduce multiple return values. Just =
as it can deduce `void` (ie: zero return values).<br class=3D""> </div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break=
-word" class=3D""><div class=3D""> Then there=E2=80=99s the point of what g=
eneric code would require to do to consistently capture the return value(s)=
of a Callable without knowing if there are one or multiple return values.<=
/div><div class=3D""><br class=3D""></div><div class=3D"">template<class=
F></div><div class=3D"">void contrived_example2(F f) {</div><div class=
=3D""> ??? x =3D f();</div><div class=3D""> ...</=
div><div class=3D"">}</div></div></blockquote><div class=3D""><br class=3D"=
">That one's easy. Since you're in generic code and could be getting multip=
le values, the only way to manipulate them is with a tuple. So that's what =
you stick them in:<br class=3D""><br class=3D"">auto x =3D make_tuple(f());=
</div><br class=3D""></div></div></blockquote></div><br class=3D""><div cla=
ss=3D"">My point was specifically that the author of the template function =
doesn=E2=80=99t necessarily know whether f has multiple return values witho=
ut type_traiting the hell out of it. I understand this would require basica=
lly almost every template function in existence with Callables to wrap ever=
y invocation in make_tuple(), just in case. Unless it is suggested to use c=
oncept shenanigans to overload the template function with concepts for all =
combinations of MRV/SRV Callable types accepted by the template function. S=
eems a bit excessive.</div><div class=3D""><br class=3D""></div></body></ht=
ml>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
--Apple-Mail=_58C5AA6B-57FB-49B2-8D4C-537D51A3440E--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 27 May 2015 08:59:36 -0700 (PDT)
Raw View
------=_Part_593_966913659.1432742376864
Content-Type: multipart/alternative;
boundary="----=_Part_594_909109964.1432742376864"
------=_Part_594_909109964.1432742376864
Content-Type: text/plain; charset=UTF-8
On Wednesday, May 27, 2015 at 11:11:34 AM UTC-4, Matthew Fioravante wrote:
>
> On Wednesday, May 27, 2015 at 3:43:10 AM UTC-4, Nicol Bolas wrote:
>
> Except that they have to pay the cost for it. Consider something simple
> like this:
>
> auto single_value()
> {
> std::string a = ...;
> return a;
> }
>
> auto multi_value()
> {
> std::string a = ...;
> std::vector b = ...;
> return [a; b];
> }
>
> `single_value` is subject to copy elision, so you should feel no problem
> with using it. Even with a small-string-optimized std::string class, you
> will get the maximum possible performance if you're using the result to
> initialize an object.
>
> With language-level multiple return values, `multi_value` would be able to
> operate under the same principle. `a` and `b` would be considered return
> values, and they would each be separately subject to elision.
>
> With your way, that's just not possible. If that syntax creates a `tuple`,
> then it must copy or move initialize the elements of that `tuple`. So even
> though the `tuple` itself is subject to elision, the creation of it is not.
>
>
> So whats stopping someone from writing a proposal to allow copy/move
> elision in your multi_value() example?
>
The fact that C++ can't do that. Remember: your [values...] syntax equates
to the construction of a `std::tuple` from the given values. Well, the
memory for those values has already been allocated, and if those are
variables, then the memory there must have been allocated elsewhere. And
because `std::tuple` is not *special*, because it must follow the regular
rules of C++, there's no way for a compiler to know (without very non-local
optimizations) exactly what that constructor is doing.
Furthermore, even if a compiler did know... what of it? Are you suggesting
that the compiler can, or should be allowed to, initialize the memory space
in a `tuple` before the object is even constructed, then ignore the tuple's
constructor?
I'd hate to have to implement that in a compiler.
> Just because it can't happen now doesn't mean we can't change the
> standard. Multi return values would be a primary use case for such a
> proposal.
>
If the standard were changed, it couldn't be changed in anything remotely
like a generic way. It would have to be based on a basic assumption that
`[values..,]` syntax doesn't generate a `std::tuple`, but some other
compiler-generated object type. And this type would be treated specially by
the language, being allowed to skip constructors.
Otherwise, you'd have to define some general way for the compiler to know
whether a constructor parameter would be stored in a tuple exactly as-is or
not.
Also what if I want to save the sequence so that I can forward it multiple
> times?
> Using your approach, I might suggest allowing auto... to capture all of
> the return values so that they can be forwarded along. This could work just
> like a variadic template parameter pack.
>
> void foo(int, float);
> [int, float] bar();
>
> auto... x = bar();
> foo(x...);
> foo(x...);
>
>
Now that... that sounds like an idea. I've always wanted a way to build a
template parameter pack.
I think that it would be possible to consider the "sequence of values"
concept to be a template parameter pack. Thus, functions can create and
return parameter packs, which can be unpacked by the user, or not unpacked
by the user, as the case may be.
So if we consider [values...] to create a parameter pack, then the
assignment syntax would look something like this:
[] = pack...;
The specific syntax can be worked out (I don't think any of these things
can move forward with `[]` notation, due to various parsing issues). But
that would be the general idea.
It wouldn't be as good as the Lua syntax. But I think this way regularizes
parameter packs as "sequences of values" in a useful way.
> But we still have the generic code problems that Miro brought up.
>
>
>
> Multiple return values means *multiple return values*, not "pack multiple
> values into some kind of object and unpack them later".
>
>
> Another kind of typelist which is standard layout compatible? Or are we no
> longer able to capture all of the return values into one object?
>
>
> If you want to capture them all in an object, you just ask for it:
>
> auto x = make_tuple(foo());
>
> That is neither hard nor particularly verbose. You can even stick them in
> an array, if all of the returned values are of the same type:
>
> auto x = make_array(foo());
>
>
> These require copy/move. In your example, unpacking is free (no-op) and
> packing requires a copy/move. In my example unpacking is free (using
> references) and packing is also free, assuming you want to continue using
> the pack type returned by the function.
>
But as previously stated, packing *is not free* in your system. Packing
requires the function doing the packing (the one returning the tuple) to
either put the values in the tuple itself or copy/move the values into the
tuple. Until you actually propose a way to fix that problem (rather than
simply declaring that it can be fixed... somehow), your proposal must be
evaluated as though such a solution doesn't exist.
>
> Or in an arbitrary data structure:
>
> auto x = std::vector<Type>{foo()};
>
> But most people using multiple return values don't capture them in a big
> object, so we don't make the syntax optimal for that case.
>
>
> Its not uncommon. Every class that has multiple "values" (e.g
> unordered_map) will be returning them in a pack using its default
> iterators so that one can write a simple range for loop.
>
And how often do people iterate through maps? The main purpose of a map is
to efficiently look up items by a key.
So I'd say it's still relatively uncommon. It's certainly not common enough
to make a special syntax for tuples.
.... *that being said*, I wouldn't mind `...` being able to unpack a tuple
or other tuple-like construct in addition to a proper parameter pack (note:
this is barring any syntactic issues, like breaking existing code).
Granted, it wouldn't resolve that problem, but it would normalize tuple as
the way to store a parameter pack as a free-standing object, rather than a
compiler construct.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_594_909109964.1432742376864
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, May 27, 2015 at 11:11:34 AM UTC-4, Matthew F=
ioravante wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r">On Wednesday, May 27, 2015 at 3:43:10 AM UTC-4, Nicol Bolas wrote:<block=
quote style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddin=
g-left:1ex"><div dir=3D"ltr"><div>Except that they have to pay the cost for=
it. Consider something simple like this:<br><br><div style=3D"background-c=
olor:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bord=
er-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#008">au=
to</span><span style=3D"color:#000"> single_value</span><span style=3D"colo=
r:#660">()</span><span style=3D"color:#000"><br></span><span style=3D"color=
:#660">{</span><span style=3D"color:#000"><br> std</span><span style=
=3D"color:#660">::</span><span style=3D"color:#008">string</span><span styl=
e=3D"color:#000"> a </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">...;</span><span style=
=3D"color:#000"><br> </span><span style=3D"color:#008">return</span><=
span style=3D"color:#000"> a</span><span style=3D"color:#660">;</span><span=
style=3D"color:#000"><br></span><span style=3D"color:#660">}</span><span s=
tyle=3D"color:#000"><br><br></span><span style=3D"color:#008">auto</span><s=
pan style=3D"color:#000"> multi_value</span><span style=3D"color:#660">()</=
span><span style=3D"color:#000"><br></span><span style=3D"color:#660">{</sp=
an><span style=3D"color:#000"><br> std</span><span style=3D"color:#66=
0">::</span><span style=3D"color:#008">string</span><span style=3D"color:#0=
00"> a </span><span style=3D"color:#660">=3D</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">...;</span><span style=3D"color:#000"=
><br> std</span><span style=3D"color:#660">::</span><span style=3D"co=
lor:#000">vector b </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">...;</span><span style=
=3D"color:#000"><br> </span><span style=3D"color:#008">return</span><=
span style=3D"color:#000"> </span><span style=3D"color:#660">[</span><span =
style=3D"color:#000">a</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"> b</span><span style=3D"color:#660">];</span><span style=3D=
"color:#000"><br></span><span style=3D"color:#660">}</span></div></code></d=
iv><br>`single_value`
is subject to copy elision, so you should feel no problem with using=20
it. Even with a small-string-optimized std::string class, you will get=20
the maximum possible performance if you're using the result to=20
initialize an object.<br><br>With language-level multiple return values,
`multi_value` would be able to operate under the same principle. `a`=20
and `b` would be considered return values, and they would each be=20
separately subject to elision.<br><br>With your way, that's just not=20
possible. If that syntax creates a `tuple`, then it must copy or move=20
initialize the elements of that `tuple`. So even though the `tuple`=20
itself is subject to elision, the creation of it is not.<br></div></div></b=
lockquote><div><br>So whats stopping someone from writing a proposal to all=
ow copy/move elision in your multi_value() example?</div></div></blockquote=
><div><br>The fact that C++ can't do that. Remember: your [values...] synta=
x equates to the construction of a `std::tuple` from the given values. Well=
, the memory for those values has already been allocated, and if those are =
variables, then the memory there must have been allocated elsewhere. And be=
cause `std::tuple` is not <i>special</i>, because it must follow the regula=
r rules of C++, there's no way for a compiler to know (without very non-loc=
al optimizations) exactly what that constructor is doing.<br><br>Furthermor=
e, even if a compiler did know... what of it? Are you suggesting that the c=
ompiler can, or should be allowed to, initialize the memory space in a `tup=
le` before the object is even constructed, then ignore the tuple's construc=
tor?<br><br>I'd hate to have to implement that in a compiler.<br> </di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Just b=
ecause it can't happen now doesn't mean we can't change the standard. Multi=
return values would be a primary use case for such a proposal.<br></div></=
div></blockquote><div><br>If the standard were changed, it couldn't be chan=
ged in anything remotely like a generic way. It would have to be based on a=
basic assumption that `[values..,]` syntax doesn't generate a `std::tuple`=
, but some other compiler-generated object type. And this type would be tre=
ated specially by the language, being allowed to skip constructors.<br><br>=
Otherwise, you'd have to define some general way for the compiler to know w=
hether a constructor parameter would be stored in a tuple exactly as-is or =
not.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"=
ltr"><div>Also what if I want to save the sequence so that I can forward it=
multiple times?<br>Using your approach, I might suggest allowing auto... t=
o capture all of the return values so that they can be forwarded along. Thi=
s could work just like a variadic template parameter pack.<br><br><div styl=
e=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border=
-style:solid;border-width:1px;word-wrap:break-word"><code><div><span style=
=3D"color:#008">void</span><span style=3D"color:#000"> foo</span><span styl=
e=3D"color:#660">(</span><span style=3D"color:#008">int</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#008">float</span><span style=3D"color:#660">);</span><span style=3D"c=
olor:#000"><br></span><span style=3D"color:#660">[</span><span style=3D"col=
or:#008">int</span><span style=3D"color:#660">,</span><span style=3D"color:=
#000"> </span><span style=3D"color:#008">float</span><span style=3D"color:#=
660">]</span><span style=3D"color:#000"> bar</span><span style=3D"color:#66=
0">();</span><span style=3D"color:#000"><br><br></span><span style=3D"color=
:#008">auto</span><span style=3D"color:#660">...</span><span style=3D"color=
:#000"> x </span><span style=3D"color:#660">=3D</span><span style=3D"color:=
#000"> bar</span><span style=3D"color:#660">();</span><span style=3D"color:=
#000"><br>foo</span><span style=3D"color:#660">(</span><span style=3D"color=
:#000">x</span><span style=3D"color:#660">...);</span><span style=3D"color:=
#000"><br>foo</span><span style=3D"color:#660">(</span><span style=3D"color=
:#000">x</span><span style=3D"color:#660">...);</span><span style=3D"color:=
#000"><br></span></div></code></div><br></div></div></blockquote><div><br>N=
ow that... that sounds like an idea. I've always wanted a way to build a te=
mplate parameter pack.<br><br>I think that it would be possible to consider=
the "sequence of values" concept to be a template parameter pack. Thus, fu=
nctions can create and return parameter packs, which can be unpacked by the=
user, or not unpacked by the user, as the case may be.<br><br>So if we con=
sider [values...] to create a parameter pack, then the assignment syntax wo=
uld look something like this:<br><br>[] =3D pack...;<br><br>The specific sy=
ntax can be worked out (I don't think any of these things can move forward =
with `[]` notation, due to various parsing issues). But that would be the g=
eneral idea.<br><br>It wouldn't be as good as the Lua syntax. But I think t=
his way regularizes parameter packs as "sequences of values" in a useful wa=
y.<br> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"=
ltr"><div>But we still have the generic code problems that Miro brought up.=
<br> </div><blockquote style=3D"margin:0;margin-left:0.8ex;border-left=
:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><br>Multiple return=
values means <i>multiple return values</i>, not "pack multiple values into=
some kind of object and unpack them later".<br> </div><blockquote sty=
le=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1e=
x"><div dir=3D"ltr"><div>
Another kind of typelist which is standard layout compatible? Or are we
no longer able to capture all of the return values into one object?</div><=
/div></blockquote><div><br>If you want to capture them all in an object, yo=
u just ask for it:<br><br><div style=3D"background-color:rgb(250,250,250);b=
order-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:=
break-word"><code><div><span style=3D"color:#008">auto</span><span style=3D=
"color:#000"> x </span><span style=3D"color:#660">=3D</span><span style=3D"=
color:#000"> make_tuple</span><span style=3D"color:#660">(</span><span styl=
e=3D"color:#000">foo</span><span style=3D"color:#660">());</span></div></co=
de></div><br>That
is neither hard nor particularly verbose. You can even stick them in an
array, if all of the returned values are of the same type:<br><br><div sty=
le=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);borde=
r-style:solid;border-width:1px;word-wrap:break-word"><code><div><span style=
=3D"color:#008">auto</span><span style=3D"color:#000"> x </span><span style=
=3D"color:#660">=3D</span><span style=3D"color:#000"> make_array</span><spa=
n style=3D"color:#660">(</span><span style=3D"color:#000">foo</span><span s=
tyle=3D"color:#660">());</span></div></code></div><br></div></div></blockqu=
ote><div><br>These require copy/move. In your example, unpacking is free (n=
o-op) and packing requires a copy/move. In my example unpacking is free (us=
ing references) and packing is also free, assuming you want to continue usi=
ng the pack type returned by the function.<br></div></div></blockquote><div=
><br>But as previously stated, packing <i>is not free</i> in your system. P=
acking requires the function doing the packing (the one returning the tuple=
) to either put the values in the tuple itself or copy/move the values into=
the tuple. Until you actually propose a way to fix that problem (rather th=
an simply declaring that it can be fixed... somehow), your proposal must be=
evaluated as though such a solution doesn't exist.<br><br></div><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><div> <=
/div><blockquote style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>Or in an arbitrary data struct=
ure:<br><br><div style=3D"background-color:rgb(250,250,250);border-color:rg=
b(187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><c=
ode><div><span style=3D"color:#008">auto</span><span style=3D"color:#000"> =
x </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> s=
td</span><span style=3D"color:#660">::</span><span style=3D"color:#000">vec=
tor</span><span style=3D"color:#660"><</span><span style=3D"color:#606">=
Type</span><span style=3D"color:#660">>{</span><span style=3D"color:#000=
">foo</span><span style=3D"color:#660">()};</span><span style=3D"color:#000=
"><br></span></div></code></div><br>But
most people using multiple return values don't capture them in a big=20
object, so we don't make the syntax optimal for that case.<br></div></div><=
/blockquote><div><br>Its not uncommon. Every class that has multiple "value=
s" (e.g unordered_map) will be returning them in a pack using its def=
ault iterators so that one can write a simple range for loop.<br></div></di=
v></blockquote><div><br>And how often do people iterate through maps? The m=
ain purpose of a map is to efficiently look up items by a key.<br><br>So I'=
d say it's still relatively uncommon. It's certainly not common enough to m=
ake a special syntax for tuples.<br><br>... <b><i>that being said</i></b>, =
I wouldn't mind `...` being able to unpack a tuple or other tuple-like cons=
truct in addition to a proper parameter pack (note: this is barring any syn=
tactic issues, like breaking existing code). Granted, it wouldn't resolve t=
hat problem, but it would normalize tuple as the way to store a parameter p=
ack as a free-standing object, rather than a compiler construct.<br></div><=
/div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
------=_Part_594_909109964.1432742376864--
------=_Part_593_966913659.1432742376864--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 27 May 2015 09:06:03 -0700
Raw View
On Wednesday 27 May 2015 11:45:43 Matthew Woehlke wrote:
> IMO (and IYIO=C2=B9 apparently) it's dangerous to allow MRV with no more
> syntax than 'return a, b'. *At minimum* I would restrict this to
> functions that have explicitly declared MRV's (which is what I was
> suggesting).
My point is that
return a, b;
Already has a meaning. Imagine (contrived example):
template <typename T> auto void do(T &&t)
{
return SomeAction(), t();
}
[int, float] void f();
Does do<f> return [int, float]? Or does it return [SomeAction, [int, float]=
]?
"Why would you do such a thing?"
template <typename T> T operator,(SomeAction, const T &t)
{
debug(t);
return t;
};
Not sure this compiles and won't produce "void value not ignored as it=20
should". This is a contrived and untested example. But I have used operator=
,=20
to debug return values before in generic code. Operator, is the only one th=
at=20
can "take" a void type as the second parameter.
http://code.qt.io/cgit/qt/qtbase.git/commit/?id=3D1991647af1de2d0b3812d5736=
3dddfeac6179a68
--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--=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/.
.
Author: Matthew Fioravante <fmatthew5876@gmail.com>
Date: Wed, 27 May 2015 09:30:13 -0700 (PDT)
Raw View
------=_Part_2068_270510071.1432744213275
Content-Type: multipart/alternative;
boundary="----=_Part_2069_239882598.1432744213275"
------=_Part_2069_239882598.1432744213275
Content-Type: text/plain; charset=UTF-8
On Wednesday, May 27, 2015 at 11:59:36 AM UTC-4, Nicol Bolas wrote:
>
> On Wednesday, May 27, 2015 at 11:11:34 AM UTC-4, Matthew Fioravante wrote:
>>
>> On Wednesday, May 27, 2015 at 3:43:10 AM UTC-4, Nicol Bolas wrote:
>>
>> Except that they have to pay the cost for it. Consider something simple
>> like this:
>>
>> auto single_value()
>> {
>> std::string a = ...;
>> return a;
>> }
>>
>> auto multi_value()
>> {
>> std::string a = ...;
>> std::vector b = ...;
>> return [a; b];
>> }
>>
>> `single_value` is subject to copy elision, so you should feel no problem
>> with using it. Even with a small-string-optimized std::string class, you
>> will get the maximum possible performance if you're using the result to
>> initialize an object.
>>
>> With language-level multiple return values, `multi_value` would be able
>> to operate under the same principle. `a` and `b` would be considered return
>> values, and they would each be separately subject to elision.
>>
>> With your way, that's just not possible. If that syntax creates a
>> `tuple`, then it must copy or move initialize the elements of that `tuple`.
>> So even though the `tuple` itself is subject to elision, the creation of it
>> is not.
>>
>>
>> So whats stopping someone from writing a proposal to allow copy/move
>> elision in your multi_value() example?
>>
>
> The fact that C++ can't do that. Remember: your [values...] syntax equates
> to the construction of a `std::tuple` from the given values. Well, the
> memory for those values has already been allocated, and if those are
> variables, then the memory there must have been allocated elsewhere. And
> because `std::tuple` is not *special*, because it must follow the regular
> rules of C++, there's no way for a compiler to know (without very non-local
> optimizations) exactly what that constructor is doing.
>
If tuple (or whatever type we use, lets call it tuple) constructor is
inline and just trivially constructs the members, as it should be then the
compiler can do whatever it wants. I don't see why the constructor cannot
construct the string directly in the memory to be used by the returned
tuple.
> Furthermore, even if a compiler did know... what of it? Are you suggesting
> that the compiler can, or should be allowed to, initialize the memory space
> in a `tuple` before the object is even constructed, then ignore the tuple's
> constructor?
>
Sure, if the constructor is inline and we can prove "as-if" compatible
behavior why not?
>
> I'd hate to have to implement that in a compiler.
>
>
>> Just because it can't happen now doesn't mean we can't change the
>> standard. Multi return values would be a primary use case for such a
>> proposal.
>>
>
> If the standard were changed, it couldn't be changed in anything remotely
> like a generic way. It would have to be based on a basic assumption that
> `[values..,]` syntax doesn't generate a `std::tuple`, but some other
> compiler-generated object type. And this type would be treated specially by
> the language, being allowed to skip constructors.
>
> Otherwise, you'd have to define some general way for the compiler to know
> whether a constructor parameter would be stored in a tuple exactly as-is or
> not.
>
> Also what if I want to save the sequence so that I can forward it multiple
>> times?
>> Using your approach, I might suggest allowing auto... to capture all of
>> the return values so that they can be forwarded along. This could work just
>> like a variadic template parameter pack.
>>
>> void foo(int, float);
>> [int, float] bar();
>>
>> auto... x = bar();
>> foo(x...);
>> foo(x...);
>>
>>
> Now that... that sounds like an idea. I've always wanted a way to build a
> template parameter pack.
>
> I think that it would be possible to consider the "sequence of values"
> concept to be a template parameter pack. Thus, functions can create and
> return parameter packs, which can be unpacked by the user, or not unpacked
> by the user, as the case may be.
>
> So if we consider [values...] to create a parameter pack, then the
> assignment syntax would look something like this:
>
> [] = pack...;
>
> The specific syntax can be worked out (I don't think any of these things
> can move forward with `[]` notation, due to various parsing issues). But
> that would be the general idea.
>
> It wouldn't be as good as the Lua syntax. But I think this way regularizes
> parameter packs as "sequences of values" in a useful way.
>
>
>> But we still have the generic code problems that Miro brought up.
>>
>>
>>
>> Multiple return values means *multiple return values*, not "pack
>> multiple values into some kind of object and unpack them later".
>>
>>
>> Another kind of typelist which is standard layout compatible? Or are we
>> no longer able to capture all of the return values into one object?
>>
>>
>> If you want to capture them all in an object, you just ask for it:
>>
>> auto x = make_tuple(foo());
>>
>> That is neither hard nor particularly verbose. You can even stick them in
>> an array, if all of the returned values are of the same type:
>>
>> auto x = make_array(foo());
>>
>>
>> These require copy/move. In your example, unpacking is free (no-op) and
>> packing requires a copy/move. In my example unpacking is free (using
>> references) and packing is also free, assuming you want to continue using
>> the pack type returned by the function.
>>
>
> But as previously stated, packing *is not free* in your system. Packing
> requires the function doing the packing (the one returning the tuple) to
> either put the values in the tuple itself or copy/move the values into the
> tuple. Until you actually propose a way to fix that problem (rather than
> simply declaring that it can be fixed... somehow), your proposal must be
> evaluated as though such a solution doesn't exist.
>
Your performance concerns are valid and I agree that any proposal would
need to address them directly and prove that they can either be mitigated
or that they are worth the cost.
>
>
>>
>> Or in an arbitrary data structure:
>>
>> auto x = std::vector<Type>{foo()};
>>
>> But most people using multiple return values don't capture them in a big
>> object, so we don't make the syntax optimal for that case.
>>
>>
>> Its not uncommon. Every class that has multiple "values" (e.g
>> unordered_map) will be returning them in a pack using its default
>> iterators so that one can write a simple range for loop.
>>
>
> And how often do people iterate through maps? The main purpose of a map is
> to efficiently look up items by a key.
>
> So I'd say it's still relatively uncommon. It's certainly not common
> enough to make a special syntax for tuples.
>
> ... *that being said*, I wouldn't mind `...` being able to unpack a tuple
> or other tuple-like construct in addition to a proper parameter pack (note:
> this is barring any syntactic issues, like breaking existing code).
> Granted, it wouldn't resolve that problem, but it would normalize tuple as
> the way to store a parameter pack as a free-standing object, rather than a
> compiler construct.
>
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2069_239882598.1432744213275
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, May 27, 2015 at 11:59:36 AM UTC-4, N=
icol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr">On Wednesday, May 27, 2015 at 11:11:34 AM UTC-4, Matthew Fioravante wro=
te:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Wednesday, M=
ay 27, 2015 at 3:43:10 AM UTC-4, Nicol Bolas wrote:<blockquote style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr"><div>Except that they have to pay the cost for it. Consider some=
thing simple like this:<br><br><div style=3D"background-color:rgb(250,250,2=
50);border-color:rgb(187,187,187);border-style:solid;border-width:1px;word-=
wrap:break-word"><code><div><span style=3D"color:#008">auto</span><span sty=
le=3D"color:#000"> single_value</span><span style=3D"color:#660">()</span><=
span style=3D"color:#000"><br></span><span style=3D"color:#660">{</span><sp=
an style=3D"color:#000"><br> std</span><span style=3D"color:#660">::<=
/span><span style=3D"color:#008">string</span><span style=3D"color:#000"> a=
</span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </=
span><span style=3D"color:#660">...;</span><span style=3D"color:#000"><br>&=
nbsp; </span><span style=3D"color:#008">return</span><span style=3D"color:#=
000"> a</span><span style=3D"color:#660">;</span><span style=3D"color:#000"=
><br></span><span style=3D"color:#660">}</span><span style=3D"color:#000"><=
br><br></span><span style=3D"color:#008">auto</span><span style=3D"color:#0=
00"> multi_value</span><span style=3D"color:#660">()</span><span style=3D"c=
olor:#000"><br></span><span style=3D"color:#660">{</span><span style=3D"col=
or:#000"><br> std</span><span style=3D"color:#660">::</span><span sty=
le=3D"color:#008">string</span><span style=3D"color:#000"> a </span><span s=
tyle=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">...;</span><span style=3D"color:#000"><br> std</span=
><span style=3D"color:#660">::</span><span style=3D"color:#000">vector b </=
span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">...;</span><span style=3D"color:#000"><br>&nbs=
p; </span><span style=3D"color:#008">return</span><span style=3D"color:#000=
"> </span><span style=3D"color:#660">[</span><span style=3D"color:#000">a</=
span><span style=3D"color:#660">;</span><span style=3D"color:#000"> b</span=
><span style=3D"color:#660">];</span><span style=3D"color:#000"><br></span>=
<span style=3D"color:#660">}</span></div></code></div><br>`single_value`
is subject to copy elision, so you should feel no problem with using=20
it. Even with a small-string-optimized std::string class, you will get=20
the maximum possible performance if you're using the result to=20
initialize an object.<br><br>With language-level multiple return values,
`multi_value` would be able to operate under the same principle. `a`=20
and `b` would be considered return values, and they would each be=20
separately subject to elision.<br><br>With your way, that's just not=20
possible. If that syntax creates a `tuple`, then it must copy or move=20
initialize the elements of that `tuple`. So even though the `tuple`=20
itself is subject to elision, the creation of it is not.<br></div></div></b=
lockquote><div><br>So whats stopping someone from writing a proposal to all=
ow copy/move elision in your multi_value() example?</div></div></blockquote=
><div><br>The fact that C++ can't do that. Remember: your [values...] synta=
x equates to the construction of a `std::tuple` from the given values. Well=
, the memory for those values has already been allocated, and if those are =
variables, then the memory there must have been allocated elsewhere. And be=
cause `std::tuple` is not <i>special</i>, because it must follow the regula=
r rules of C++, there's no way for a compiler to know (without very non-loc=
al optimizations) exactly what that constructor is doing.<br></div></div></=
blockquote><div><br>If tuple (or whatever type we use, lets call it tuple) =
constructor is inline and just trivially constructs the members, as it shou=
ld be then the compiler can do whatever it wants. I don't see why the const=
ructor cannot construct the string directly in the memory to be used by the=
returned tuple. <br><br></div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr"><div><br>Furthermore, even if a compiler did know... what=
of it? Are you suggesting that the compiler can, or should be allowed to, =
initialize the memory space in a `tuple` before the object is even construc=
ted, then ignore the tuple's constructor?<br></div></div></blockquote><div>=
<br>Sure, if the constructor is inline and we can prove "as-if" compatible =
behavior why not?<br> <br></div><blockquote class=3D"gmail_quote" styl=
e=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left:=
1ex;"><div dir=3D"ltr"><div><br>I'd hate to have to implement that in a co=
mpiler.<br> </div><blockquote class=3D"gmail_quote" style=3D"margin:0;=
margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"=
ltr"><div>Just because it can't happen now doesn't mean we can't change the=
standard. Multi return values would be a primary use case for such a propo=
sal.<br></div></div></blockquote><div><br>If the standard were changed, it =
couldn't be changed in anything remotely like a generic way. It would have =
to be based on a basic assumption that `[values..,]` syntax doesn't generat=
e a `std::tuple`, but some other compiler-generated object type. And this t=
ype would be treated specially by the language, being allowed to skip const=
ructors.<br></div></div></blockquote><blockquote class=3D"gmail_quote" styl=
e=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left:=
1ex;"><div dir=3D"ltr"><div><br>Otherwise, you'd have to define some gener=
al way for the compiler to know whether a constructor parameter would be st=
ored in a tuple exactly as-is or not.<br><br></div><blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><div>Also what if I want to save the seque=
nce so that I can forward it multiple times?<br>Using your approach, I migh=
t suggest allowing auto... to capture all of the return values so that they=
can be forwarded along. This could work just like a variadic template para=
meter pack.<br><br><div style=3D"background-color:rgb(250,250,250);border-c=
olor:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-w=
ord"><code><div><span style=3D"color:#008">void</span><span style=3D"color:=
#000"> foo</span><span style=3D"color:#660">(</span><span style=3D"color:#0=
08">int</span><span style=3D"color:#660">,</span><span style=3D"color:#000"=
> </span><span style=3D"color:#008">float</span><span style=3D"color:#660">=
);</span><span style=3D"color:#000"><br></span><span style=3D"color:#660">[=
</span><span style=3D"color:#008">int</span><span style=3D"color:#660">,</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#008">float</sp=
an><span style=3D"color:#660">]</span><span style=3D"color:#000"> bar</span=
><span style=3D"color:#660">();</span><span style=3D"color:#000"><br><br></=
span><span style=3D"color:#008">auto</span><span style=3D"color:#660">...</=
span><span style=3D"color:#000"> x </span><span style=3D"color:#660">=3D</s=
pan><span style=3D"color:#000"> bar</span><span style=3D"color:#660">();</s=
pan><span style=3D"color:#000"><br>foo</span><span style=3D"color:#660">(</=
span><span style=3D"color:#000">x</span><span style=3D"color:#660">...);</s=
pan><span style=3D"color:#000"><br>foo</span><span style=3D"color:#660">(</=
span><span style=3D"color:#000">x</span><span style=3D"color:#660">...);</s=
pan><span style=3D"color:#000"><br></span></div></code></div><br></div></di=
v></blockquote><div><br>Now that... that sounds like an idea. I've always w=
anted a way to build a template parameter pack.<br><br>I think that it woul=
d be possible to consider the "sequence of values" concept to be a template=
parameter pack. Thus, functions can create and return parameter packs, whi=
ch can be unpacked by the user, or not unpacked by the user, as the case ma=
y be.<br><br>So if we consider [values...] to create a parameter pack, then=
the assignment syntax would look something like this:<br><br>[] =3D pack..=
..;<br><br>The specific syntax can be worked out (I don't think any of these=
things can move forward with `[]` notation, due to various parsing issues)=
.. But that would be the general idea.<br><br>It wouldn't be as good as the =
Lua syntax. But I think this way regularizes parameter packs as "sequences =
of values" in a useful way.<br> </div><blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr"><div>But we still have the generic code problems t=
hat Miro brought up.<br> </div><blockquote style=3D"margin:0;margin-le=
ft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div=
><br>Multiple return values means <i>multiple return values</i>, not "pack =
multiple values into some kind of object and unpack them later".<br> <=
/div><blockquote style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>
Another kind of typelist which is standard layout compatible? Or are we
no longer able to capture all of the return values into one object?</div><=
/div></blockquote><div><br>If you want to capture them all in an object, yo=
u just ask for it:<br><br><div style=3D"background-color:rgb(250,250,250);b=
order-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:=
break-word"><code><div><span style=3D"color:#008">auto</span><span style=3D=
"color:#000"> x </span><span style=3D"color:#660">=3D</span><span style=3D"=
color:#000"> make_tuple</span><span style=3D"color:#660">(</span><span styl=
e=3D"color:#000">foo</span><span style=3D"color:#660">());</span></div></co=
de></div><br>That
is neither hard nor particularly verbose. You can even stick them in an
array, if all of the returned values are of the same type:<br><br><div sty=
le=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);borde=
r-style:solid;border-width:1px;word-wrap:break-word"><code><div><span style=
=3D"color:#008">auto</span><span style=3D"color:#000"> x </span><span style=
=3D"color:#660">=3D</span><span style=3D"color:#000"> make_array</span><spa=
n style=3D"color:#660">(</span><span style=3D"color:#000">foo</span><span s=
tyle=3D"color:#660">());</span></div></code></div><br></div></div></blockqu=
ote><div><br>These require copy/move. In your example, unpacking is free (n=
o-op) and packing requires a copy/move. In my example unpacking is free (us=
ing references) and packing is also free, assuming you want to continue usi=
ng the pack type returned by the function.<br></div></div></blockquote><div=
><br>But as previously stated, packing <i>is not free</i> in your system. P=
acking requires the function doing the packing (the one returning the tuple=
) to either put the values in the tuple itself or copy/move the values into=
the tuple. Until you actually propose a way to fix that problem (rather th=
an simply declaring that it can be fixed... somehow), your proposal must be=
evaluated as though such a solution doesn't exist.<br></div></div></blockq=
uote><div><br>Your performance concerns are valid and I agree that any prop=
osal would need to address them directly and prove that they can either be =
mitigated or that they are worth the cost.<br> </div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc=
solid;padding-left:1ex"><div dir=3D"ltr"><div></div><div> </div><bloc=
kquote style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddi=
ng-left:1ex"><div dir=3D"ltr"><div>Or in an arbitrary data structure:<br><b=
r><div 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><div><=
span style=3D"color:#008">auto</span><span style=3D"color:#000"> x </span><=
span style=3D"color:#660">=3D</span><span style=3D"color:#000"> std</span><=
span style=3D"color:#660">::</span><span style=3D"color:#000">vector</span>=
<span style=3D"color:#660"><</span><span style=3D"color:#606">Type</span=
><span style=3D"color:#660">>{</span><span style=3D"color:#000">foo</spa=
n><span style=3D"color:#660">()};</span><span style=3D"color:#000"><br></sp=
an></div></code></div><br>But
most people using multiple return values don't capture them in a big=20
object, so we don't make the syntax optimal for that case.<br></div></div><=
/blockquote><div><br>Its not uncommon. Every class that has multiple "value=
s" (e.g unordered_map) will be returning them in a pack using its def=
ault iterators so that one can write a simple range for loop.<br></div></di=
v></blockquote><div><br>And how often do people iterate through maps? The m=
ain purpose of a map is to efficiently look up items by a key.<br><br>So I'=
d say it's still relatively uncommon. It's certainly not common enough to m=
ake a special syntax for tuples.<br><br>... <b><i>that being said</i></b>, =
I wouldn't mind `...` being able to unpack a tuple or other tuple-like cons=
truct in addition to a proper parameter pack (note: this is barring any syn=
tactic issues, like breaking existing code). Granted, it wouldn't resolve t=
hat problem, but it would normalize tuple as the way to store a parameter p=
ack as a free-standing object, rather than a compiler construct.<br></div><=
/div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
------=_Part_2069_239882598.1432744213275--
------=_Part_2068_270510071.1432744213275--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 27 May 2015 10:44:45 -0700
Raw View
On Wednesday 27 May 2015 12:44:11 Matthew Woehlke wrote:
> > template <typename T> auto void do(T &&t)
> > {
> > return SomeAction(), t();
> > }
> >
> >
> >
> > [int, float] void f();
> >
> >
> >
> > Does do<f> return [int, float]? Or does it return [SomeAction, [int,
> > float]]?
> The former; 'do' wasn't explicitly declared to have MRV. (This is even
> if we allow MRV without new syntax, which as stated, I'm not comfortable
> with, for the same reasons you're objecting to it.)
Ok, so
template <typename T> decltype(t()) do(T &&);
Is that an explicit MRV?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 27 May 2015 13:06:23 -0700 (PDT)
Raw View
------=_Part_6377_467348959.1432757183797
Content-Type: multipart/alternative;
boundary="----=_Part_6378_1386256834.1432757183797"
------=_Part_6378_1386256834.1432757183797
Content-Type: text/plain; charset=UTF-8
On Wednesday, May 27, 2015 at 12:30:13 PM UTC-4, Matthew Fioravante wrote:
>
> On Wednesday, May 27, 2015 at 11:59:36 AM UTC-4, Nicol Bolas wrote:
>>
>> On Wednesday, May 27, 2015 at 11:11:34 AM UTC-4, Matthew Fioravante wrote:
>>>
>>> On Wednesday, May 27, 2015 at 3:43:10 AM UTC-4, Nicol Bolas wrote:
>>>
>>> Except that they have to pay the cost for it. Consider something simple
>>> like this:
>>>
>>> auto single_value()
>>> {
>>> std::string a = ...;
>>> return a;
>>> }
>>>
>>> auto multi_value()
>>> {
>>> std::string a = ...;
>>> std::vector b = ...;
>>> return [a; b];
>>> }
>>>
>>> `single_value` is subject to copy elision, so you should feel no problem
>>> with using it. Even with a small-string-optimized std::string class, you
>>> will get the maximum possible performance if you're using the result to
>>> initialize an object.
>>>
>>> With language-level multiple return values, `multi_value` would be able
>>> to operate under the same principle. `a` and `b` would be considered return
>>> values, and they would each be separately subject to elision.
>>>
>>> With your way, that's just not possible. If that syntax creates a
>>> `tuple`, then it must copy or move initialize the elements of that `tuple`.
>>> So even though the `tuple` itself is subject to elision, the creation of it
>>> is not.
>>>
>>>
>>> So whats stopping someone from writing a proposal to allow copy/move
>>> elision in your multi_value() example?
>>>
>>
>> The fact that C++ can't do that. Remember: your [values...] syntax
>> equates to the construction of a `std::tuple` from the given values. Well,
>> the memory for those values has already been allocated, and if those are
>> variables, then the memory there must have been allocated elsewhere. And
>> because `std::tuple` is not *special*, because it must follow the
>> regular rules of C++, there's no way for a compiler to know (without very
>> non-local optimizations) exactly what that constructor is doing.
>>
>
> If tuple (or whatever type we use, lets call it tuple) constructor is
> inline and just trivially constructs the members, as it should be then the
> compiler can do whatever it wants. I don't see why the constructor cannot
> construct the string directly in the memory to be used by the returned
> tuple.
>
OK, let's stop using `tuple`, because `tuple` is not able to do anything
even remotely like what you're talking about. `tuple`'s constructor is a
highly recursive beast. Many implementations of `tuple` don't even store
the values as their particular types; they use std::aligned_storage or
something internally. Lastly, we don't want compilers to rely on the
implementation details of `tuple`, much like `{}` syntax doesn't return an
array, but a special type supplied by the compiler.
So let's just say you have a simple struct:
struct Simple
{
std::string str;
int foo;
};
No tricks, no internal gimmicks; it is the simplest possible case. Given
that:
std::string in = ...;
return Simple{in, 2};
Right now, the standard requires that `in` be copied into `Simple`. You
want the standard to allow the compiler to elide the copy, and thus
construct `in` in the place where `Simple` will be constructed.
There's one really big hurdle here. You are literally talking about eliding *part
of a constructor*. After all, you're not eliding the entire constructor
here; you still need to copy that 2 in there. So... how would "partial
constructor elision" work? Would it only be restricted to aggregates? If
not, then the compiler has to somehow cull out parts of a constructor.
Even if you limit it to only constructors that have no function body and
are "inline", you're still requiring the compiler to break down a
constructor into separate steps. And if you allow constructor bodies, how
exactly does that work?
>
>> Furthermore, even if a compiler did know... what of it? Are you
>> suggesting that the compiler can, or should be allowed to, initialize the
>> memory space in a `tuple` before the object is even constructed, then
>> ignore the tuple's constructor?
>>
>
> Sure, if the constructor is inline and we can prove "as-if" compatible
> behavior why not?
>
Because elision is not "'as-if' compatible behavior". Elision changes
visible behavior; that's why the standard has to explicitly allow it under
certain circumstances.
The questions you need to answer are:
1) How do you specify it? Oh, I know how you say it in English. But what is
it in standardese? The language for return value elision is very simple.
It's one sentence in 12.8 section 31. Your "partial constructor elision" is
much more complex.
2) Can you actually implement it? This requires some significant knowledge
of compilers. Can compilers adequately detect when they can employ elision?
Can compilers break constructors down into pieces that they can choose to
execute or not, based on which parts are elided? This is very much
non-trivial, and you should not assume that they can simply work it out.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_6378_1386256834.1432757183797
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, May 27, 2015 at 12:30:13 PM UTC-4, Matthew F=
ioravante wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r">On Wednesday, May 27, 2015 at 11:59:36 AM UTC-4, Nicol Bolas wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Wednesday, May 27, 2=
015 at 11:11:34 AM UTC-4, Matthew Fioravante wrote:<blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr">On Wednesday, May 27, 2015 at 3:43:10 AM U=
TC-4, Nicol Bolas wrote:<blockquote style=3D"margin:0;margin-left:0.8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Except that=
they have to pay the cost for it. Consider something simple like this:<br>=
<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,18=
7,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><div=
><span style=3D"color:#008">auto</span><span style=3D"color:#000"> single_v=
alue</span><span style=3D"color:#660">()</span><span style=3D"color:#000"><=
br></span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br=
> std</span><span style=3D"color:#660">::</span><span style=3D"color:=
#008">string</span><span style=3D"color:#000"> a </span><span style=3D"colo=
r:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660">...;</span><span style=3D"color:#000"><br> </span><span style=3D=
"color:#008">return</span><span style=3D"color:#000"> a</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">}</span><span style=3D"color:#000"><br><br></span><span sty=
le=3D"color:#008">auto</span><span style=3D"color:#000"> multi_value</span>=
<span style=3D"color:#660">()</span><span style=3D"color:#000"><br></span><=
span style=3D"color:#660">{</span><span style=3D"color:#000"><br> std=
</span><span style=3D"color:#660">::</span><span style=3D"color:#008">strin=
g</span><span style=3D"color:#000"> a </span><span style=3D"color:#660">=3D=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">...;</=
span><span style=3D"color:#000"><br> std</span><span style=3D"color:#=
660">::</span><span style=3D"color:#000">vector b </span><span style=3D"col=
or:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">...;</span><span style=3D"color:#000"><br> </span><span style=
=3D"color:#008">return</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">[</span><span style=3D"color:#000">a</span><span style=3D"c=
olor:#660">;</span><span style=3D"color:#000"> b</span><span style=3D"color=
:#660">];</span><span style=3D"color:#000"><br></span><span style=3D"color:=
#660">}</span></div></code></div><br>`single_value`
is subject to copy elision, so you should feel no problem with using=20
it. Even with a small-string-optimized std::string class, you will get=20
the maximum possible performance if you're using the result to=20
initialize an object.<br><br>With language-level multiple return values,
`multi_value` would be able to operate under the same principle. `a`=20
and `b` would be considered return values, and they would each be=20
separately subject to elision.<br><br>With your way, that's just not=20
possible. If that syntax creates a `tuple`, then it must copy or move=20
initialize the elements of that `tuple`. So even though the `tuple`=20
itself is subject to elision, the creation of it is not.<br></div></div></b=
lockquote><div><br>So whats stopping someone from writing a proposal to all=
ow copy/move elision in your multi_value() example?</div></div></blockquote=
><div><br>The fact that C++ can't do that. Remember: your [values...] synta=
x equates to the construction of a `std::tuple` from the given values. Well=
, the memory for those values has already been allocated, and if those are =
variables, then the memory there must have been allocated elsewhere. And be=
cause `std::tuple` is not <i>special</i>, because it must follow the regula=
r rules of C++, there's no way for a compiler to know (without very non-loc=
al optimizations) exactly what that constructor is doing.<br></div></div></=
blockquote><div><br>If tuple (or whatever type we use, lets call it tuple) =
constructor is inline and just trivially constructs the members, as it shou=
ld be then the compiler can do whatever it wants. I don't see why the const=
ructor cannot construct the string directly in the memory to be used by the=
returned tuple.<br></div></div></blockquote><div><br>OK, let's stop using =
`tuple`, because `tuple` is not able to do anything even remotely like what=
you're talking about. `tuple`'s constructor is a highly recursive beast. M=
any implementations of `tuple` don't even store the values as their particu=
lar types; they use std::aligned_storage or something internally. Lastly, w=
e don't want compilers to rely on the implementation details of `tuple`, mu=
ch like `{}` syntax doesn't return an array, but a special type supplied by=
the compiler.<br><br>So let's just say you have a simple struct:<br><br><d=
iv class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); bor=
der-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; word=
-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprin=
t"><span style=3D"color: #008;" class=3D"styled-by-prettify">struct</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #606;" class=3D"styled-by-prettify">Simple</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br> std</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">::</span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">string</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> str</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br> </span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
foo</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></code></di=
v><br>No tricks, no internal gimmicks; it is the simplest possible case. Gi=
ven that:<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(=
250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bord=
er-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div cla=
ss=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::=
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">string</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">in</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">...;</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br><br></span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Si=
mple</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">in</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #0=
66;" class=3D"styled-by-prettify">2</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">};</span></div></code></div><br>Right now, the sta=
ndard requires that `in` be copied into `Simple`. You want the standard to =
allow the compiler to elide the copy, and thus construct `in` in the place =
where `Simple` will be constructed.<br><br>There's one really big hurdle he=
re. You are literally talking about eliding <i>part of a constructor</i>. A=
fter all, you're not eliding the entire constructor here; you still need to=
copy that 2 in there. So... how would "partial constructor elision" work? =
Would it only be restricted to aggregates? If not, then the compiler has to=
somehow cull out parts of a constructor.<br><br>Even if you limit it to on=
ly constructors that have no function body and are "inline", you're still r=
equiring the compiler to break down a constructor into separate steps. And =
if you allow constructor bodies, how exactly does that work?<br><br></div><=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div=
><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><br>Furtherm=
ore, even if a compiler did know... what of it? Are you suggesting that the=
compiler can, or should be allowed to, initialize the memory space in a `t=
uple` before the object is even constructed, then ignore the tuple's constr=
uctor?<br></div></div></blockquote><div><br>Sure, if the constructor is inl=
ine and we can prove "as-if" compatible behavior why not?<br></div></div></=
blockquote><div><br>Because elision is not "'as-if' compatible behavior". E=
lision changes visible behavior; that's why the standard has to explicitly =
allow it under certain circumstances.<br><br>The questions you need to answ=
er are:<br><br>1) How do you specify it? Oh, I know how you say it in Engli=
sh. But what is it in standardese? The language for return value elision is=
very simple. It's one sentence in 12.8 section 31. Your "partial construct=
or elision" is much more complex.<br><br>2) Can you actually implement it? =
This requires some significant knowledge of compilers. Can compilers adequa=
tely detect when they can employ elision? Can compilers break constructors =
down into pieces that they can choose to execute or not, based on which par=
ts are elided? This is very much non-trivial, and you should not assume tha=
t they can simply work it out.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
------=_Part_6378_1386256834.1432757183797--
------=_Part_6377_467348959.1432757183797--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 27 May 2015 13:13:54 -0700
Raw View
On Wednesday 27 May 2015 12:10:32 Matthew Woehlke wrote:
> What I meant was that MRV by value sequence (your proposal) should make
> it possible for me to write 'unpack', as in this example:
>
> int foo(int, int, int);
>
> std::tuple<int, int, int> params = { ... };
> foo(unpack(params));
This is unlikely.
Far more likely:
unpack(foo, params);
This is already achievable today
template <typename F, typename... Args, size_t... N> auto
unpack(F &&f, std::tuple<Args...> &&args,
std::index_sequence<N...> = std::index_sequence_for<Args...>())
{
using namespace std;
return f(std::forward<Args>(get<N>(args))...);
}
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 27 May 2015 13:26:52 -0700
Raw View
On Wednesday 27 May 2015 13:16:10 Cleiton Santoia wrote:
> template<typename ...Types>
>
> tuple (const initializer_list<Types...>& elems);
I like this, since it also allows me to do heterogeneous maps without having
to create a std::initializer_list<Entry<Typesafe, Typesafe>>. I can't make
that "Typesafe" inner type work for types unknown at build time without heavy
type erasure.
make_map({{"foo", 1}, {"bar", "hello"}, {0, false}});
maybe without the outer { } too
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 27 May 2015 15:55:51 -0700
Raw View
On Wednesday 27 May 2015 15:09:33 Nicol Bolas wrote:
> We do have a similar concept: template parameter packs. It is one entity
> which represents multiple objects. You can unpack them in arbitrary
> expressions, which makes them much more useful than your limited `unpack`
> tuple suggestion.
Actually, thinking about it and fold expressions allows for very easy
unpacking. The unpack-tuple-and-call function would be:
template <typename F, typename... Args> auto
unpack(F &&f, std::tuple<Args...> &&args)
{
using namespace std;
return f(std::forward<Args>(get<N>(args)), ...);
}
So all we need is for the MRV pack to be treated like a template parameter
pack and we can use all the expansion tricks.
std::cout << ... << args << endl;
size_t sum = 0 + ... + args; // assuming they cast somehow to integer
tuple<decltype(args)...> t = make_tuple(..., args);
If you have a template pack containing an MRV pack, you'll need the .......
operator...
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Miro Knejp <miro.knejp@gmail.com>
Date: Thu, 28 May 2015 12:13:37 +0200
Raw View
--Apple-Mail=_34CD8621-A2E5-4D5D-84E6-112A6BEA6BBE
Content-Type: text/plain; charset=UTF-8
> On 28 May 2015, at 00:55 , Thiago Macieira <thiago@macieira.org> wrote:
>
> On Wednesday 27 May 2015 15:09:33 Nicol Bolas wrote:
>> We do have a similar concept: template parameter packs. It is one entity
>> which represents multiple objects. You can unpack them in arbitrary
>> expressions, which makes them much more useful than your limited `unpack`
>> tuple suggestion.
>
> Actually, thinking about it and fold expressions allows for very easy
> unpacking. The unpack-tuple-and-call function would be:
>
> template <typename F, typename... Args> auto
> unpack(F &&f, std::tuple<Args...> &&args)
> {
> using namespace std;
> return f(std::forward<Args>(get<N>(args)), ...);
> }
This is already part of the Library Fundamentals TS in [tuple.apply]
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html>
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--Apple-Mail=_34CD8621-A2E5-4D5D-84E6-112A6BEA6BBE
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dus-ascii"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode=
: space; -webkit-line-break: after-white-space;" class=3D""><br class=3D"">=
<div><blockquote type=3D"cite" class=3D""><div class=3D"">On 28 May 2015, a=
t 00:55 , Thiago Macieira <<a href=3D"mailto:thiago@macieira.org" class=
=3D"">thiago@macieira.org</a>> wrote:</div><br class=3D"Apple-interchang=
e-newline"><div class=3D"">On Wednesday 27 May 2015 15:09:33 Nicol Bolas wr=
ote:<br class=3D""><blockquote type=3D"cite" class=3D"">We do have a simila=
r concept: template parameter packs. It is one entity <br class=3D"">which =
represents multiple objects. You can unpack them in arbitrary <br class=3D"=
">expressions, which makes them much more useful than your limited `unpack`=
<br class=3D"">tuple suggestion.<br class=3D""></blockquote><br class=3D""=
>Actually, thinking about it and fold expressions allows for very easy <br =
class=3D"">unpacking. The unpack-tuple-and-call function would be:<br class=
=3D""><br class=3D"">template <typename F, typename... Args> auto<br =
class=3D"">unpack(F &&f, std::tuple<Args...> &&args)<=
br class=3D"">{<br class=3D""> us=
ing namespace std;<br class=3D"">  =
;return f(std::forward<Args>(get<N>(args)), ...);<br class=3D""=
>}<br class=3D""></div></blockquote><div><br class=3D""></div>This is alrea=
dy part of the Library Fundamentals TS in [tuple.apply]</div><div><a href=
=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html" cla=
ss=3D"">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html<=
/a></div><div><br class=3D""></div></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" 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 />
--Apple-Mail=_34CD8621-A2E5-4D5D-84E6-112A6BEA6BBE--
.
Author: Miro Knejp <miro.knejp@gmail.com>
Date: Tue, 2 Jun 2015 14:17:47 +0200
Raw View
I was thinking some more about how this could be implemented and just wante=
d to give my viewpoint on this.
Disclaimer: In all examples below I assume the comma operator does not exis=
t and is more or less pseudocode to make it more readable. Syntax bikeshedd=
ing 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 func=
tion performs RVO the compiler transforms this signature in something like
void foo(T* result, A a, B b);
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, tran=
sforming the function into
struct __Result { T t; U u; V v; };
void bar(__Result* result, A a, B b);
This assumes all three types are copyable or at least movable to their fina=
l destination.
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=20
__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 sc=
ope. It could be recycled for other variables, but just saying.
There is of course an alternative way how the signature can be transformed:
void baz(T* t, U* u, V* v, A a, B b);
Here RVO can be applied directly to each individual result value. This mean=
s the caller is much more flexible in where to store the results:
#3 (semantically equivalent to #1)
T t; // not initialized
U u; // not initialized
V v; // not initialized
baz(&t, &u, &v, a, b);
#4 (semantically equivalent to #2)
T t;
U u;
V v; // not initialized
{
T __t; // not initialized
U __u; // not initialized
baz(&__t, &__u, &v, a, b);
t =3D std::move(__t);
u =3D std::move(__u);
}
There is no difference in the number of operations but #4 is more efficient=
in stack space usage than #2, but it has to push 2 more pointers on the ca=
ll stack, however that stack space for __t and __u is occupied only tempora=
rily.
This is how I think the compiler might realize multiple return values with =
RVO support. People who actually write compilers for a living probably have=
some aces up their sleeves.
The first option with an implementation-defined and ABI-consistent out-stru=
cture only requires one additional argument to the function, however the ca=
ller is severely restricted in how it can layout code around the invocation=
.. The second option requires more arguments to the call, meaning pushing mo=
re stuff on the stack, however it gives the caller more options to eliminat=
e stack overhead.
This difference is important when it comes to argument passing:
void consume(T t, U u, V v);
Let=E2=80=99s examine the expressions "consume(foo(a, b))" if realized with=
either bar() or baz():
#5
{
__Result __result; // not initialized
bar(&__result, a, b);
consume(std::move(__result.t), std::move(__result.u), std::move(__result.=
v))
}
#6
{
T __t; // not initialized
U __u; // not initialized
V __v; // not initialized
baz(&__t, __u, __v, a, b);
consume(std::move(__t), std::move(__u), std::move(__v))
}
Again, same number of operations, *but* in #6 the compiler can arrange the =
storage for __t, __u, and __v in such a way that they can be passed directl=
y into consume without move:
#7
{
T __t; // not initialized
U __u; // not initialized
V __v; // not initialized
baz(&__t, __u, __v, a, b);
call consume // __t, __u and __v are pre-allocated at the stack locations=
required for consume() call
}
This optimization gets rid of the moves and allows in-place construction of=
the parameters to consume(). This may not be possible with #5 if the layou=
t of the structure is not exactly the same as the layout of the same argume=
nt sequence to a function (and obviously if no conversions are required).
Solutions #2, #4, #6 and #7 become much more difficult (if not impossible) =
if the structure used for transporting the return values is not compiler-ge=
nerated but a user provided std::tuple, std::pair or anything else that is =
not =E2=80=9Cmagic=E2=80=9D or with the exact layout required by the ABI.
I guess my whole point here is that there are at least two ways to implemen=
t this that need to be hammered into the ABI and dictate how much flexibili=
ty the caller has and how much call overhead there is per return value (1 o=
r n additional pointers pushed). Once there is a syntax for this compiler-g=
enerated unpacking it can surely be extended to user-defined types. I just =
don=E2=80=99t think that there is as much elision potential for user-define=
d types.
--=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/.
.
Author: Miro Knejp <miro.knejp@gmail.com>
Date: Tue, 2 Jun 2015 17:54:58 +0200
Raw View
> On 02 Jun 2015, at 16:22 , Matthew Woehlke <mw_triad@users.sourceforge.ne=
t> wrote:
>=20
> On 2015-06-02 08:17, Miro Knejp wrote:
>> Now imagine we have multiple return values:
>>=20
>> T, U, V bar(A a, B b)
>>=20
>> In the best-case scenario RVO is possible for all three return values, t=
ransforming the function into
>>=20
>> struct __Result { T t; U u; V v; };
>> void bar(__Result* result, A a, B b);
>>=20
>> This assumes all three types are copyable or at least movable to their f=
inal destination.
>=20
> ...no? With RVO you are *not* copying/moving, you are constructing in
> place. (Well, IIRC the standard requires that they *be* copyable, but
> the point is that they won't actually *be* copied.)
Right, that statement referred to a previous version of the example and I j=
ust forgot to remove the sentence. Though it still does apply if the values=
must be moved out of __result to a *final destination*.
>=20
>=20
>=20
>> [snip lots]
>> I guess my whole point here is that there are at least two ways to=20
>> implement this that need to be hammered into the ABI and dictate how=20
>> 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.
>=20
> Two questions:
>=20
> 1. Is the overhead of passing more pointers to the called function worth
> the benefits? I ask objectively. I think your argument is convincing,
> but ultimately a qualified answer to this question is desired before
> choosing an implementation. (This may not be a question to be answered
> by the standard, either, but by compiler vendors.)
I do not have any measurements so I don=E2=80=99t know. In the end this is =
for the ABI designers to decide. As I said though, if __Result has the *exa=
ct same* layout as is required for the same sequence of parameters for a fu=
nction call then the single-pointer version only has the "potentially waste=
d=E2=80=9D stack space of partial __Result structures if it cannot be re-us=
ed in the same scope. However in the real world there are also parameters p=
assed in registers, so this all becomes a little more complicated. I guess =
the functions could instead be transformed as
__Result foo(A a, B b);
and let the already existing ABI rules for compound type returns apply.
>=20
> 2. Can the second form allow for code such as the following example? Is
> there a necessary performance penalty?
>=20
> auto results =3D foo();
> for (;;)
> bar(results...);
>=20
> (Doesn't need to be an infinite loop, so long as the compiler is
> prevented from transforming the separate call and assignment into
> 'bar(foo()...)'.)
>=20
This is basically equivalent to
auto a =3D =E2=80=A6
auto b =3D =E2=80=A6
auto c =3D ...
for(;;)
bar(a, b, c);
The only real difference is how the parameters are initialized but since th=
e values captured in =E2=80=9Cresults=E2=80=9D are lvalues the usual proced=
ure applies. The scenario bar(foo()) is somewhat a special case because foo=
() produces prvalues which are immediately consumed by bar().
--=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/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Tue, 02 Jun 2015 09:48:54 -0700
Raw View
On Tuesday 02 June 2015 14:17:47 Miro Knejp wrote:
> I guess my whole point here is that there are at least two ways to implem=
ent
> this that need to be hammered into the ABI and dictate how much flexibili=
ty
> 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 much elision potential=
for
> user-defined types.
Conclusions from this explanation:
a) there are multiple ways to skin a cat, with tradeoffs. The compiler writ=
ers=20
will need to decide how to do this on their own. If you want to participate=
in=20
the discussion, subscribe to the cxx-abi mailing list. :-)
b) the compiler should be free to choose how to return the multiple types,=
=20
which precludes reusing std::tuple for this. The syntax should either have =
a=20
new, "compiler magic" type or simply not specify a type at all.
--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--=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/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 2 Jun 2015 11:46:48 -0700 (PDT)
Raw View
------=_Part_218_449059535.1433270808811
Content-Type: multipart/alternative;
boundary="----=_Part_219_1086069187.1433270808811"
------=_Part_219_1086069187.1433270808811
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
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=20
> wanted to give my viewpoint on this.=20
>
> Disclaimer: In all examples below I assume the comma operator does not=20
> exist and is more or less pseudocode to make it more readable. Syntax=20
> bikeshedding can be done once the semantic issues are solved. I also assu=
me=20
> none of the functions are inlined.=20
>
> Consider how RVO is typically done today. Given the function=20
>
> T foo(A a, B b);=20
>
> and assuming T is too big to be passed in registers. Now imagining the=20
> function performs RVO the compiler transforms this signature in something=
=20
> like=20
>
> 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);
I say that because it isn't a `T` yet; it's `foo` that initailizes the=20
memory into a `T`. Also because:
=20
> Now imagine we have multiple return values:=20
>
> T, U, V bar(A a, B b)=20
>
> In the best-case scenario RVO is possible for all three return values,=20
> transforming the function into=20
>
> struct __Result { T t; U u; V v; };=20
> void bar(__Result* result, A a, B b);
>
Then you get to ignore the whole `__Result` thing. Consider a more complete=
=20
version of both of these. If you have:
T t =3D foo(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] =3D foo(a, b);
//Becomes:
void *__temp =3D __alloc_from_stack(sizeof(T) + sizeof(U) + sizeof(V)); //I=
gnoring=20
obvious 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 =3D *(reinterpret_cast<U*>(reinterpret_cast<char *>(__temp) + sizeof(T
))); //Again ignore alignment
V &v =3D *(reinterpret_cast<V*>(reinterpret_cast<char *>(__temp) + sizeof(T=
) +=20
sizeof(U))); //Again ignore alignment
This way, we don't have to think in terms of explicit "structs"; it's all=
=20
just memory and ABI layout.
This assumes all three types are copyable or at least movable to their=20
> final destination.=20
>
If you ever do `T t =3D foo();`, the compiler *requires* that no there is a=
n=20
accessible copy/move constructor. The copy/move operation may be elided,=20
but it still must be accessible.
=20
> In the case where all three return values are used for initialization thi=
s=20
> is pretty trivial.=20
>
> T t, U u, V v =3D bar(a, b);=20
>
> transforms into=20
>
> #1=20
> __Result __result; // not initialized=20
> bar(&__result, a, b);=20
> // t, u, v are now aliases to __result.t, __result.u, __result.v=20
>
> Now what if the initialization is different=20
>
> #2=20
> T t;=20
> U u;=20
> t, u, V v =3D bar(a, b);=20
>
> This must be transformed to=20
>
> __Result __result; // not initialized=20
> bar(&__result, A a, B b);=20
> // v is now an alias to result.v=20
> t =3D std::move(__result.t);=20
> u =3D std::move(__result.u);=20
> __result.u.~U();=20
> __result.t.~T();=20
>
> This means there is wasted stack space for t and u (due to the fixed=20
> layout of __Result) __result.t and __result.u have to stay until v goes o=
ut=20
> 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 store=
=20
the result into a live object? Of course you have to copy/move the result=
=20
into it. Elision only when when you *initializing* the return value.
MRV doesn't change that in any way.=20
=20
> I guess my whole point here is that there are at least two ways to=20
> implement this that need to be hammered into the ABI and dictate how much=
=20
> flexibility the caller has and how much call overhead there is per return=
=20
> value (1 or n additional pointers pushed). Once there is a syntax for thi=
s=20
> compiler-generated unpacking it can surely be extended to user-defined=20
> types. I just don=E2=80=99t think that there is as much elision potential=
for=20
> user-defined types.
Except that there's plenty of elision of potential for user-defined types.=
=20
Indeed, modern C++ syntax is designed around the assumption that elision=20
exists and will make code as fast as possible. Every time you see someone=
=20
write `T t =3D stuff();` instead of an explicit `stuff(&t, );`, you are=20
implicitly relying on elision to make this fast.
Why should MRVs undo this syntactic progress?
--=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/.
------=_Part_219_1086069187.1433270808811
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<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-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">I was thinking so=
me more about how this could be implemented and just wanted to give my view=
point 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 bikes=
hedding 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 l=
ike
<br>
<br>void foo(T* result, A a, B b);<br></blockquote><div><br>It would be bet=
ter to say that the compiler turns it into:<br><br>void foo(void *result, A=
a, B b);<br><br>I say that because it isn't a `T` yet; it's `foo` that ini=
tailizes the memory into a `T`. Also because:<br> </div><blockquote cl=
ass=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><br><div class=3D"prettyprint" style=3D"=
background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); bor=
der-style: solid; border-width: 1px; word-wrap: break-word;"><code class=3D=
"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #000;" cl=
ass=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-pr=
ettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">a=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> b</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"col=
or: #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"> </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">*</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">__temp </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> __alloc_from_stack</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">sizeof</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">T</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">));</span><span styl=
e=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: #6=
60;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> a</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> b</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>T </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">&</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">t </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">*(</span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">reinterpret_cast</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">*>(</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify">__temp</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">));</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: r=
gb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break=
-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">[</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">T t</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> U u</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> V v</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">]</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><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">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">a</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> b</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><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"> </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">*</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">__temp </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> __alloc_from_stack</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">sizeof</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>+</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">sizeof</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">U</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">+</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">sizeof</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">V</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">));</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #800;" class=3D"styled-by-prettify">//Ignoring obvious alignment issues =
here</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>fo=
o</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">,</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> a</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> b</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><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">&</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">t </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">*(</span><span style=3D"color: =
#008;" class=3D"styled-by-prettify">reinterpret_cast</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify">T</span><span style=3D"color: #660;" cl=
ass=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">));</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br>U </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">&</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">u </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">*(</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">reinterpret_cast</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">U</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">*>(</span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">reinterpret_cast</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">char</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">*>(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">__temp</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">+</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">sizeof</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">T</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">)));</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"style=
d-by-prettify">//Again ignore alignment</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>V </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">&</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">v </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">*(</=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">reinterpret_=
cast</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">V</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">*>(</span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">reinterpret_cast</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">char</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </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;" cl=
ass=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">+</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">sizeof</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify">T</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">+</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">sizeof</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">U</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">)));</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">//Again ignore alignment</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></d=
iv></code></div><br>This way, we don't have to think in terms of explicit&n=
bsp; "structs"; it's all just memory and ABI layout.<br><br></div><blockquo=
te 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 fina=
l 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> </=
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 thre=
e 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(&__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=20
<br>
<br>__Result __result; // not initialized
<br>bar(&__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 la=
yout of __Result) __result.t and __result.u have to stay until v goes out o=
f scope. It could be recycled for other variables, but just saying.<br></bl=
ockquote><div><br>How is that any different from the single return value ca=
se, when you store the result into a live object? Of course you have to cop=
y/move the result into it. Elision only when when you <i>initializing</i> t=
he return value.<br><br>MRV doesn't change that in any way. <br> </div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;">
I guess my whole point here is that there are at least two ways to implemen=
t this that need to be hammered into the ABI and dictate how much flexibili=
ty the caller has and how much call overhead there is per return value (1 o=
r n additional pointers pushed). Once there is a syntax for this compiler-g=
enerated unpacking it can surely be extended to user-defined types. I just =
don=E2=80=99t think that there is as much elision potential for user-define=
d types.</blockquote><div><br>Except that there's plenty of elision of pote=
ntial 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(&t, );`, you are implicitly relying on elision to make this fast=
..<br><br>Why should MRVs undo this syntactic progress?<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
------=_Part_219_1086069187.1433270808811--
------=_Part_218_449059535.1433270808811--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Tue, 02 Jun 2015 13:27:50 -0700
Raw View
On Tuesday 02 June 2015 11:46:48 Nicol Bolas wrote:
> 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 = stuff();` instead of an explicit `stuff(&t, );`, you are
> implicitly relying on elision to make this fast.
>
> Why should MRVs undo this syntactic progress?
In fact, our investigation showed that compilers optimise inline functions
with multiple return values (structs, pairs, tuples) better than those with
output parameters.
For an example, see https://codereview.qt-project.org/106089.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 2 Jun 2015 15:39:25 -0700 (PDT)
Raw View
------=_Part_412_1214575718.1433284765307
Content-Type: multipart/alternative;
boundary="----=_Part_413_1542027691.1433284765307"
------=_Part_413_1542027691.1433284765307
Content-Type: text/plain; charset=UTF-8
On Tuesday, June 2, 2015 at 4:27:55 PM UTC-4, Thiago Macieira wrote:
>
> On Tuesday 02 June 2015 11:46:48 Nicol Bolas wrote:
> > 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 = stuff();` instead of an explicit `stuff(&t, );`, you are
> > implicitly relying on elision to make this fast.
> >
> > Why should MRVs undo this syntactic progress?
>
> In fact, our investigation showed that compilers optimise inline functions
> with multiple return values (structs, pairs, tuples) better than those
> with
> output parameters.
>
> For an example, see https://codereview.qt-project.org/106089.
>
That's... enlightening. That sounds like a pretty good argument for
transition the FileSystem TS's error-code "returning" variations to using
something like `expected` when it gets to the final standard.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_413_1542027691.1433284765307
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, June 2, 2015 at 4:27:55 PM UTC-4, Thia=
go Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Tuesday 0=
2 June 2015 11:46:48 Nicol Bolas wrote:
<br>> Except that there's plenty of elision of potential for user-define=
d types.=20
<br>> Indeed, modern C++ syntax is designed around the assumption that e=
lision=20
<br>> exists and will make code as fast as possible. Every time you see =
someone=20
<br>> write `T t =3D stuff();` instead of an explicit `stuff(&t, );`=
, you are=20
<br>> implicitly relying on elision to make this fast.
<br>>=20
<br>> Why should MRVs undo this syntactic progress?
<br>
<br>In fact, our investigation showed that compilers optimise inline functi=
ons=20
<br>with multiple return values (structs, pairs, tuples) better than those =
with=20
<br>output parameters.
<br>
<br>For an example, see <a href=3D"https://codereview.qt-project.org/106089=
" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https://ww=
w.google.com/url?q\75https%3A%2F%2Fcodereview.qt-project.org%2F106089\46sa\=
75D\46sntz\0751\46usg\75AFQjCNGbc9kuqSwSnDqaJ8-7t3pcv_gQrQ';return true;" o=
nclick=3D"this.href=3D'https://www.google.com/url?q\75https%3A%2F%2Fcoderev=
iew.qt-project.org%2F106089\46sa\75D\46sntz\0751\46usg\75AFQjCNGbc9kuqSwSnD=
qaJ8-7t3pcv_gQrQ';return true;">https://codereview.qt-project.<wbr>org/1060=
89</a>.
<br></blockquote><div><br>That's... enlightening. That sounds like a pretty=
good argument for transition the FileSystem TS's error-code "returning" va=
riations to using something like `expected` when it gets to the final stand=
ard.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
------=_Part_413_1542027691.1433284765307--
------=_Part_412_1214575718.1433284765307--
.
Author: Miro Knejp <miro.knejp@gmail.com>
Date: Wed, 03 Jun 2015 00:50:59 +0200
Raw View
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">&</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"><<=
/span><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">__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">&</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"><<=
/span><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">__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">&</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"><<=
/span><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: #008;" class=3D"styled-by-prettify">reint=
erpret_cast</span><span
style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/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">*>=
(</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">&</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"><<=
/span><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: #008;" class=3D"styled-by-prettify">reint=
erpret_cast</span><span
style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/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">*>=
(</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(&__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(&__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(&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" 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--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Tue, 02 Jun 2015 16:38:15 -0700
Raw View
On Tuesday 02 June 2015 15:39:25 Nicol Bolas wrote:
> > In fact, our investigation showed that compilers optimise inline
> > functions
> > with multiple return values (structs, pairs, tuples) better than those
> > with
> > output parameters.
> >
> > For an example, see https://codereview.qt-project.org/106089.
>
> That's... enlightening. That sounds like a pretty good argument for
> transition the FileSystem TS's error-code "returning" variations to using
> something like `expected` when it gets to the final standard.
Note that this was about inline functions and I believe the presence of the
output parameter throws the inliner off.
For out-of-line functions, the difference is going to be related to the ABI:
does the ABI return a trivial aggregate in registers or does it do that by
hidden parameter? There's no common answer, as this depends on register size,
structure size and whether it's trivially copyable and trivially destructible.
But I'd design the API using std::expected instead of out parameters. There
will be few cases where having the extra error condition causes a return-in-
registers to turn into return-by-hidden-parameter.
I'd also expect that std::expected obviates the need for overloads that throw.
Instead, the throw could be inserted automatically by the std::expected access
to the result.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Wed, 03 Jun 2015 05:43:48 +0200
Raw View
This is a multi-part message in MIME format.
--------------080107040408000407050302
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 03/06/15 00:39, Nicol Bolas a =C3=A9crit :
>
>
> On Tuesday, June 2, 2015 at 4:27:55 PM UTC-4, Thiago Macieira wrote:
>
> On Tuesday 02 June 2015 11:46:48 Nicol Bolas wrote:
> > 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(&t, );`,
> you are
> > implicitly relying on elision to make this fast.
> >
> > Why should MRVs undo this syntactic progress?
>
> In fact, our investigation showed that compilers optimise inline
> functions
> with multiple return values (structs, pairs, tuples) better than
> those with
> output parameters.
>
> For an example, see https://codereview.qt-project.org/106089
> <https://codereview.qt-project.org/106089>.
>
>
Glad to see that some compilers perform better with a functional=20
interface, at least when functions are inlined.
> That's... enlightening. That sounds like a pretty good argument for=20
> transition the FileSystem TS's error-code "returning" variations to=20
> using something like `expected` when it gets to the final standard.
>
Nicol, maybe it is worth adding a performance ax to your document about=20
error reporting techniques.
Vicente
--=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/.
--------------080107040408000407050302
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">
<div class=3D"moz-cite-prefix">Le 03/06/15 00:39, Nicol Bolas a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:20ff0095-a634-40a7-8c01-3b302ece9bd3@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
<br>
On Tuesday, June 2, 2015 at 4:27:55 PM UTC-4, Thiago Macieira
wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On
Tuesday 02 June 2015 11:46:48 Nicol Bolas wrote:
<br>
> Except that there's plenty of elision of potential for
user-defined types. <br>
> Indeed, modern C++ syntax is designed around the
assumption that elision <br>
> exists and will make code as fast as possible. Every time
you see someone <br>
> write `T t =3D stuff();` instead of an explicit
`stuff(&t, );`, you are <br>
> implicitly relying on elision to make this fast.
<br>
> <br>
> Why should MRVs undo this syntactic progress?
<br>
<br>
In fact, our investigation showed that compilers optimise
inline functions <br>
with multiple return values (structs, pairs, tuples) better
than those with <br>
output parameters.
<br>
<br>
For an example, see <a moz-do-not-send=3D"true"
href=3D"https://codereview.qt-project.org/106089"
target=3D"_blank" rel=3D"nofollow"
onmousedown=3D"this.href=3D'https://www.google.com/url?q\75http=
s%3A%2F%2Fcodereview.qt-project.org%2F106089\46sa\75D\46sntz\0751\46usg\75A=
FQjCNGbc9kuqSwSnDqaJ8-7t3pcv_gQrQ';return
true;"
onclick=3D"this.href=3D'https://www.google.com/url?q\75https%3A=
%2F%2Fcodereview.qt-project.org%2F106089\46sa\75D\46sntz\0751\46usg\75AFQjC=
NGbc9kuqSwSnDqaJ8-7t3pcv_gQrQ';return
true;">https://codereview.qt-project.<wbr>org/106089</a>.
<br>
</blockquote>
<div><br>
</div>
</div>
</blockquote>
Glad to see that some compilers perform better with a functional
interface, at least when functions are inlined.<br>
<blockquote
cite=3D"mid:20ff0095-a634-40a7-8c01-3b302ece9bd3@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>That's... enlightening. That sounds like a pretty good
argument for transition the FileSystem TS's error-code
"returning" variations to using something like `expected` when
it gets to the final standard.</div>
</div>
<br>
</blockquote>
Nicol, maybe it is worth adding a performance ax to your document
about error reporting techniques.<br>
<br>
Vicente<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" 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 />
--------------080107040408000407050302--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 2 Jun 2015 21:50:46 -0700 (PDT)
Raw View
------=_Part_689_2111797770.1433307046917
Content-Type: multipart/alternative;
boundary="----=_Part_690_1522886421.1433307046917"
------=_Part_690_1522886421.1433307046917
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, June 2, 2015 at 11:43:50 PM UTC-4, Vicente J. Botet Escriba=20
wrote:
>
> Le 03/06/15 00:39, Nicol Bolas a =C3=A9crit :
> =20
>
>
> On Tuesday, June 2, 2015 at 4:27:55 PM UTC-4, Thiago Macieira wrote:=20
>>
>> On Tuesday 02 June 2015 11:46:48 Nicol Bolas wrote:=20
>> > Except that there's plenty of elision of potential for user-defined=20
>> types.=20
>> > Indeed, modern C++ syntax is designed around the assumption that=20
>> elision=20
>> > exists and will make code as fast as possible. Every time you see=20
>> someone=20
>> > write `T t =3D stuff();` instead of an explicit `stuff(&t, );`, you ar=
e=20
>> > implicitly relying on elision to make this fast.=20
>> >=20
>> > Why should MRVs undo this syntactic progress?=20
>>
>> In fact, our investigation showed that compilers optimise inline=20
>> functions=20
>> with multiple return values (structs, pairs, tuples) better than those=
=20
>> with=20
>> output parameters.=20
>>
>> For an example, see https://codereview.qt-project.org/106089.=20
>>
>
> Glad to see that some compilers perform better with a functional=20
> interface, at least when functions are inlined.
>
> That's... enlightening. That sounds like a pretty good argument for=20
> transition the FileSystem TS's error-code "returning" variations to using=
=20
> something like `expected` when it gets to the final standard.
> =20
> Nicol, maybe it is worth adding a performance ax to your document about=
=20
> error reporting techniques.
>
Performance is a difficult thing to quantify, particularly with regard to=
=20
error handling. Is part of the cost of `expected` the fact that the return=
=20
type may have grown in size? Is part of the cost of exceptions the compiler=
=20
cost of generating stack-unwinding code? Do you consider the performance of=
=20
throwing the exception, or simply the performance of the various `try`=20
blocks (if that's even a performance issue at all)? Do we include the cost=
=20
of accessing a potentially mutex-locked object in out-of-band schemes?
Also, don't think of that document as proprietary; feel free to add to it=
=20
yourself if you see a deficiency. I don't feel knowledgeable enough to be=
=20
able to reasonably discuss the various performance characteristics of these=
=20
error reporting mechanisms, but if you do, that would be a reasonable=20
addition.
--=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/.
------=_Part_690_1522886421.1433307046917
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, June 2, 2015 at 11:43:50 PM UTC-4, Vic=
ente J. Botet Escriba wrote:<blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 03/06/15 00:39, Nicol Bolas a
=C3=A9crit :<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr"><br>
<br>
On Tuesday, June 2, 2015 at 4:27:55 PM UTC-4, Thiago Macieira
wrote:
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">On
Tuesday 02 June 2015 11:46:48 Nicol Bolas wrote:
<br>
> Except that there's plenty of elision of potential for
user-defined types. <br>
> Indeed, modern C++ syntax is designed around the
assumption that elision <br>
> exists and will make code as fast as possible. Every time
you see someone <br>
> write `T t =3D stuff();` instead of an explicit
`stuff(&t, );`, you are <br>
> implicitly relying on elision to make this fast.
<br>
> <br>
> Why should MRVs undo this syntactic progress?
<br>
<br>
In fact, our investigation showed that compilers optimise
inline functions <br>
with multiple return values (structs, pairs, tuples) better
than those with <br>
output parameters.
<br>
<br>
For an example, see <a href=3D"https://codereview.qt-project.org/=
106089" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.href=3D'http=
s://www.google.com/url?q\75https%3A%2F%2Fcodereview.qt-project.org%2F106089=
\46sa\75D\46sntz\0751\46usg\75AFQjCNGbc9kuqSwSnDqaJ8-7t3pcv_gQrQ';return tr=
ue;" onclick=3D"this.href=3D'https://www.google.com/url?q\75https%3A%2F%2Fc=
odereview.qt-project.org%2F106089\46sa\75D\46sntz\0751\46usg\75AFQjCNGbc9ku=
qSwSnDqaJ8-7t3pcv_gQrQ';return true;">https://codereview.qt-project.<wbr>or=
g/106089</a>.
<br>
</blockquote>
<div><br>
</div>
</div>
</blockquote>
Glad to see that some compilers perform better with a functional
interface, at least when functions are inlined.<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>That's... enlightening. That sounds like a pretty good
argument for transition the FileSystem TS's error-code
"returning" variations to using something like `expected` when
it gets to the final standard.</div>
</div>
<br>
</blockquote>
Nicol, maybe it is worth adding a performance ax to your document
about error reporting techniques.<br></div></blockquote><div><br>Perfor=
mance is a difficult thing to quantify, particularly with regard to error h=
andling. Is part of the cost of `expected` the fact that the return type ma=
y have grown in size? Is part of the cost of exceptions the compiler cost o=
f generating stack-unwinding code? Do you consider the performance of throw=
ing the exception, or simply the performance of the various `try` blocks (i=
f that's even a performance issue at all)? Do we include the cost of access=
ing a potentially mutex-locked object in out-of-band schemes?<br><br>Also, =
don't think of that document as proprietary; feel free to add to it yoursel=
f if you see a deficiency. I don't feel knowledgeable enough to be able to =
reasonably discuss the various performance characteristics of these error r=
eporting mechanisms, but if you do, that would be a reasonable addition.<br=
></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
------=_Part_690_1522886421.1433307046917--
------=_Part_689_2111797770.1433307046917--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Wed, 03 Jun 2015 08:20:32 +0200
Raw View
This is a multi-part message in MIME format.
--------------070809030204080304030004
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 03/06/15 06:50, Nicol Bolas a =C3=A9crit :
>
>
> On Tuesday, June 2, 2015 at 11:43:50 PM UTC-4, Vicente J. Botet=20
> Escriba wrote:
>
> Le 03/06/15 00:39, Nicol Bolas a =C3=A9crit :
>>
>>
>> On Tuesday, June 2, 2015 at 4:27:55 PM UTC-4, Thiago Macieira wrote:
>>
>> On Tuesday 02 June 2015 11:46:48 Nicol Bolas wrote:
>> > 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(&t,
>> );`, you are
>> > implicitly relying on elision to make this fast.
>> >
>> > Why should MRVs undo this syntactic progress?
>>
>> In fact, our investigation showed that compilers optimise
>> inline functions
>> with multiple return values (structs, pairs, tuples) better
>> than those with
>> output parameters.
>>
>> For an example, see https://codereview.qt-project.org/106089
>> <https://codereview.qt-project.org/106089>.
>>
>>
> Glad to see that some compilers perform better with a functional
> interface, at least when functions are inlined.
>> That's... enlightening. That sounds like a pretty good argument
>> for transition the FileSystem TS's error-code "returning"
>> variations to using something like `expected` when it gets to the
>> final standard.
>>
> Nicol, maybe it is worth adding a performance ax to your document
> about error reporting techniques.
>
>
> Performance is a difficult thing to quantify, particularly with regard=20
> to error handling. Is part of the cost of `expected` the fact that the=20
> return type may have grown in size? Is part of the cost of exceptions=20
> the compiler cost of generating stack-unwinding code? Do you consider=20
> the performance of throwing the exception, or simply the performance=20
> of the various `try` blocks (if that's even a performance issue at=20
> all)? Do we include the cost of accessing a potentially mutex-locked=20
> object in out-of-band schemes?
>
> Also, don't think of that document as proprietary; feel free to add to=20
> it yourself if you see a deficiency. I don't feel knowledgeable enough=20
> to be able to reasonably discuss the various performance=20
> characteristics of these error reporting mechanisms, but if you do,=20
> that would be a reasonable addition.
>
I was not asking you to do the work, just if you consider it is worth=20
doing it and if performance considerations are something that can be=20
included in it.
From your response, I deduce that yes, it is worth doing it.
I'll be not interested in comparing exception and expected based=20
interfaces, but just error_code output parameters and expected (return=20
variant) based interfaces.
Thanks,
Vicente
--=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/.
--------------070809030204080304030004
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">
<div class=3D"moz-cite-prefix">Le 03/06/15 06:50, Nicol Bolas a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:3e68596f-1a33-481c-acfe-c230b212234c@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
<br>
On Tuesday, June 2, 2015 at 11:43:50 PM UTC-4, Vicente J. Botet
Escriba wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 03/06/15 00:39, Nicol Bolas a =C3=A9crit=C2=A0:<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr"><br>
<br>
On Tuesday, June 2, 2015 at 4:27:55 PM UTC-4, Thiago
Macieira wrote:
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex">On Tuesday 02 June 2015
11:46:48 Nicol Bolas wrote: <br>
> Except that there's plenty of elision of
potential for user-defined types. <br>
> Indeed, modern C++ syntax is designed around the
assumption that elision <br>
> exists and will make code as fast as possible.
Every time you see someone <br>
> write `T t =3D stuff();` instead of an explicit
`stuff(&t, );`, you are <br>
> implicitly relying on elision to make this fast.
<br>
> <br>
> Why should MRVs undo this syntactic progress? <br>
<br>
In fact, our investigation showed that compilers
optimise inline functions <br>
with multiple return values (structs, pairs, tuples)
better than those with <br>
output parameters. <br>
<br>
For an example, see <a moz-do-not-send=3D"true"
href=3D"https://codereview.qt-project.org/106089"
rel=3D"nofollow" target=3D"_blank"
onmousedown=3D"this.href=3D'https://www.google.com/url?=
q\75https%3A%2F%2Fcodereview.qt-project.org%2F106089\46sa\75D\46sntz\0751\4=
6usg\75AFQjCNGbc9kuqSwSnDqaJ8-7t3pcv_gQrQ';return
true;"
onclick=3D"this.href=3D'https://www.google.com/url?q\75=
https%3A%2F%2Fcodereview.qt-project.org%2F106089\46sa\75D\46sntz\0751\46usg=
\75AFQjCNGbc9kuqSwSnDqaJ8-7t3pcv_gQrQ';return
true;">https://codereview.qt-project.<wbr>org/106089</a=
>.
<br>
</blockquote>
<div><br>
</div>
</div>
</blockquote>
Glad to see that some compilers perform better with a
functional interface, at least when functions are inlined.<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>That's... enlightening. That sounds like a pretty
good argument for transition the FileSystem TS's
error-code "returning" variations to using something
like `expected` when it gets to the final standard.</div>
</div>
<br>
</blockquote>
Nicol, maybe it is worth adding a performance ax to your
document about error reporting techniques.<br>
</div>
</blockquote>
<div><br>
Performance is a difficult thing to quantify, particularly
with regard to error handling. Is part of the cost of
`expected` the fact that the return type may have grown in
size? Is part of the cost of exceptions the compiler cost of
generating stack-unwinding code? Do you consider the
performance of throwing the exception, or simply the
performance of the various `try` blocks (if that's even a
performance issue at all)? Do we include the cost of accessing
a potentially mutex-locked object in out-of-band schemes?<br>
<br>
Also, don't think of that document as proprietary; feel free
to add to it yourself if you see a deficiency. I don't feel
knowledgeable enough to be able to reasonably discuss the
various performance characteristics of these error reporting
mechanisms, but if you do, that would be a reasonable
addition.<br>
</div>
</div>
<br>
</blockquote>
I was not asking you to do the work, just if you consider it is
worth doing it and if performance considerations are something that
can be included in it.<br>
From your response, I deduce that yes, it is worth doing it.<br>
<br>
I'll be not interested in comparing exception and expected based
interfaces, but just error_code output parameters and expected
(return variant) based interfaces. <br>
<br>
Thanks,<br>
Vicente<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" 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 />
--------------070809030204080304030004--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Tue, 2 Jun 2015 23:31:29 -0700
Raw View
--f46d0438940d8f64e1051797353f
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tue, Jun 2, 2015 at 11:20 PM, Vicente J. Botet Escriba <
vicente.botet@wanadoo.fr> wrote:
> Le 03/06/15 06:50, Nicol Bolas a =C3=A9crit :
>
> On Tuesday, June 2, 2015 at 11:43:50 PM UTC-4, Vicente J. Botet Escriba
> wrote:
>>
>> Le 03/06/15 00:39, Nicol Bolas a =C3=A9crit :
>>
>> On Tuesday, June 2, 2015 at 4:27:55 PM UTC-4, Thiago Macieira wrote:
>>>
>>> On Tuesday 02 June 2015 11:46:48 Nicol Bolas wrote:
>>> > 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(&t, );`, you a=
re
>>> > implicitly relying on elision to make this fast.
>>> >
>>> > Why should MRVs undo this syntactic progress?
>>>
>>> In fact, our investigation showed that compilers optimise inline
>>> functions
>>> with multiple return values (structs, pairs, tuples) better than those
>>> with
>>> output parameters.
>>>
>>> For an example, see https://codereview.qt-project.org/106089.
>>>
>>
>> Glad to see that some compilers perform better with a functional
>> interface, at least when functions are inlined.
>>
>
In this decade, the idea that compilers are really good at value semantics
(e.g. creating new values and returning them) and relatively not-so-good at
reference semantics (e.g. passing around references to use as
out-parameters) should not be shocking to anybody. *Of course* value
semantics are going to win that fight.
For those who need convincing, Chandler Carruth's keynote from CppCon 2013
covers this topic extremely well.
https://www.youtube.com/watch?v=3DeR34r7HOU14
=E2=80=93Arthur
--=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/.
--f46d0438940d8f64e1051797353f
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tue, Jun 2, 2015 at 11:20 PM, Vicente J. Botet Escriba =
<span dir=3D"ltr"><<a href=3D"mailto:vicente.botet@wanadoo.fr" target=3D=
"_blank">vicente.botet@wanadoo.fr</a>></span> wrote:<br><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(=
204,204,204);border-left-style:solid;padding-left:1ex">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 03/06/15 06:50, Nicol Bolas a
=C3=A9crit=C2=A0:</div><span class=3D""><blockquote type=3D"cite">
<div dir=3D"ltr">
On Tuesday, June 2, 2015 at 11:43:50 PM UTC-4, Vicente J. Botet
Escriba wrote:
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex=
;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style=
:solid;padding-left:1ex">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 03/06/15 00:39, Nicol Bolas a =C3=A9crit=C2=A0:</div><b=
lockquote type=3D"cite"><div dir=3D"ltr">
On Tuesday, June 2, 2015 at 4:27:55 PM UTC-4, Thiago
Macieira wrote:
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0=
px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-le=
ft-style:solid;padding-left:1ex">On Tuesday 02 June 2015
11:46:48 Nicol Bolas wrote: <br>
> Except that there's plenty of elision of
potential for user-defined types. <br>
> Indeed, modern C++ syntax is designed around the
assumption that elision <br>
> exists and will make code as fast as possible.
Every time you see someone <br>
> write `T t =3D stuff();` instead of an explicit
`stuff(&t, );`, you are <br>
> implicitly relying on elision to make this fast.
<br>
> <br>
> Why should MRVs undo this syntactic progress? <br>
<br>
In fact, our investigation showed that compilers
optimise inline functions <br>
with multiple return values (structs, pairs, tuples)
better than those with <br>
output parameters. <br>
<br>
For an example, see <a href=3D"https://codereview.qt-proj=
ect.org/106089" rel=3D"nofollow" target=3D"_blank">https://codereview.qt-pr=
oject.org/106089</a>.
<br>
</blockquote>
<div><br>
</div>
</div>
</blockquote>
Glad to see that some compilers perform better with a
functional interface, at least when functions are inlined.<br>
</div></blockquote></div></blockquote></span></div></blockquote=
><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0=
px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-le=
ft-style:solid;padding-left:1ex"><div class=3D""><div class=3D"h5"></div></=
div></blockquote></div></div><div class=3D"gmail_extra">In this decade, the=
idea that compilers are really good at value semantics (e.g. creating new =
values and returning them) and relatively not-so-good at reference semantic=
s (e.g. passing around references to use as out-parameters) should not be s=
hocking to anybody. =C2=A0<i>Of course</i> value semantics are going to win=
that fight.<br></div><div class=3D"gmail_extra"><br></div><div class=3D"gm=
ail_extra"><div class=3D"gmail_extra">For those who need convincing, Chandl=
er Carruth's keynote from CppCon 2013 covers this topic extremely well.=
</div><div class=3D"gmail_extra"><a href=3D"https://www.youtube.com/watch?v=
=3DeR34r7HOU14">https://www.youtube.com/watch?v=3DeR34r7HOU14</a><br></div>=
<div><br></div></div><div class=3D"gmail_extra">=E2=80=93Arthur</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
--f46d0438940d8f64e1051797353f--
.
Author: Matthew Fioravante <fmatthew5876@gmail.com>
Date: Tue, 9 Jun 2015 07:52:09 -0700 (PDT)
Raw View
------=_Part_509_914129642.1433861529249
Content-Type: multipart/alternative;
boundary="----=_Part_510_678882456.1433861529249"
------=_Part_510_678882456.1433861529249
Content-Type: text/plain; charset=UTF-8
Don't know if any of you have been following this thread, but here is
another use case for MRV:
https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/sIVuvuZ1NCw
template <typename IntegralL,typename IntegralR> [auto,bool] add_carry(
IntegralL l, IntegralR r);
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_510_678882456.1433861529249
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Don't know if any of you have been following this th=
read, but here is another use case for MRV:<br><br>https://groups.google.co=
m/a/isocpp.org/forum/#!topic/std-proposals/sIVuvuZ1NCw<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: brea=
k-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">template</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">typename</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">IntegralL</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">typename</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-pretti=
fy">IntegralR</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">></span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">[</span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">bool</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">]</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> add_carry</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #606;" class=3D"style=
d-by-prettify">IntegralL</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> l</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #606;" class=3D"styled-by-prettify">IntegralR</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> r</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></code></di=
v><br><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
------=_Part_510_678882456.1433861529249--
------=_Part_509_914129642.1433861529249--
.