Topic: N4074: Thoughts and considerations


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 2 Oct 2015 11:39:01 -0700 (PDT)
Raw View
------=_Part_508_478071751.1443811141438
Content-Type: multipart/alternative;
 boundary="----=_Part_509_55844961.1443811141440"

------=_Part_509_55844961.1443811141440
Content-Type: text/plain; charset=UTF-8

Last year, Herb Sutter proposed N4074
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4074.pdf> (PDF),
which allowed return statements to use direct-list-initialization rather
than copy-list-initialization rules. For those who don't recall,
copy-list-initialization says that, if a braced-init-list selects an
`explicit` constructor, you get a compiler error.

I don't think I've ever seen quite so many papers written in response to a
single proposal before. Three
<http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4094.html>
separate
<http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4131.html> papers
<http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4223.html> were
written savaging the very idea of the proposal. As such, it was quickly
discarded.

However, there is still something there *in principle*. That something
being the notion that you should not have to type a typename more than once.

This is the idea behind auto return type deduction, after all. It allows
you to just do this:

auto func(...)
{
  SomeType blah;
  ...
  return blah;
}

The compiler figures out what you meant. `blah` has an explicit type, and
that type (minus references) will be the return value of the function. No
problems.

Therefore, if you needed to return something like a tuple, you'd do this:

auto func(...)
{
  ...
  return std::make_tuple(4, 9.5f);
}

And that all works.

Well, it works right up until you're in a position where you *cannot* use
return type deduction. Not all functions are written in headers. And maybe
once modules come around, we'll be able to ignore return types outside of
exceptional cases. But for today, you have to state an explicit type:

std::tuple<int, float> func(...)
{
  ...
  return std::tuple<int, float>(4, 9.5f);
}

I hope I don't ever have to change what this function returns. Otherwise,
I'd have to do it in two places.

That being said, all of the reasons that have been stated for allowing
`return {4, 9.5f}` to just "work" are still perfectly valid. N4074 is the
wrong solution.

That does not mean that it's not a problem worth solving.

All three response papers ultimately cite one major problem: you've
*implicitly* broken the contract between the writer of the type and the
user of the type. By declaring that constructor `explicit`, the writer of
the type said, "I don't want implicit conversions to call this function."
To therefore allow an implicit conversion to do so would break the contract.

The user's problem with this is that he's already mentioned the typename
once before; he shouldn't have to do it again.

So let's solve that problem: give the user a way to perform explicit
conversions *without* using the typename. For example:

std::tuple<int, float> func(...)
{
  ...
  return explicit {4, 9.5f};
}

There: problem solved. The user has explicitly stated their desire for a
conversion, thus satisfying the class writer's contract. And the user
doesn't have to use the typename in question; the compiler knows what it is.

Here's how an example from N4094 would look and behave:

tuple<seconds, nanoseconds>
test1()
{
    return explicit{3, 4};
}

tuple<seconds, nanoseconds>
test2()
{
    return explicit{3h, 4ms};
}

tuple<int, float, string>
test3()
{
    return explicit{3, 4.5, "text"};
}

We want test1 to be rejected, due to the inability to implicitly convert
from integers to time units. But we want test2 and test3 to be accepted,
since those types can be implicitly converted.

And this is how it ought to work.

However:

tuple<seconds, nanoseconds>
test4()
{
    return explicit{explicit{3}, explicit{4}};
}

This would also work. The two explicit-qualified braced-init-lists do exact
what they say: explicitly convert from an integer to `seconds`.

What is to stop users from qualifying ever parameter with `explicit`, thus
rendering `explicit` constructors meaningless? Syntactic noise: nobody
wants to read or write `explicit` that much. Just look at how noisy `test4`
is compared to `test2`.

This should ensure that it will be used *sparingly*.

Does this seem feasible, to *generally allow* (not just in return
statements) `explicit` followed by braced-init-list to convert
copy-list-initialization into direct-list-initialization? Does putting a
keyword there sufficient to satisfy the `explicit` contract on constructors?

Note that the feature would *only* work on braced-init-lists. So you
couldn't do something like `explicit 5`; you have to qualify it.

*And then, something else occurred to me*

A few years back, I was playing around with some ideas about fixing the
"uniform initialization is not uniform" problem. That problem being that
`vector<int>` hides several of its constructors from braced-init-lists, and
therefore you cannot reliably have `vector<T> t{5};` mean to actually call
the constructor in template code.

I also remembered an early version of uniform initialization which did
indeed completely ignore the implicit/explicit distinction on constructors.
That all braced-initialization was direct list initialization.

Well, if `explicit {}` is explicitly taking those back to those rules...
why not have `explicit {}` *also* change the rules about what the `{}`
actually means.

That is, create a third type of braced initialization:
explicit-list-initialization. Such initialization looks exactly like
direct-list-initialization, save for one change:

It *never* implicitly calls initializer_list constructors.

Therefore:

vector<T> t = explicit {5}; //Always calls the constructor taking a single
integer argument.
vector<T> t = explicit {5, 3, 4, -9}; //Always a compile error.
vector<T> t = explicit {{5, 3, 4, -9}}; //May attempt to call an
initializer list constructor.

I justify the use of `explicit` for this for one reason: pretty much
*nobody* declares initializer list constructors `explicit`. They want you
to use them by default, and you still can.

It's just that now, we have a way to call

This will also resolve some issues with allocator construct. That being the
inability to initialize aggregates. `allocator::construct` can be rewritten
to (by default) use `explicit {std::forward<Args>(args)...}`. And you won't
lose access to any constructors this way.

Any thoughts? Is this as insane as it sounds, or is this actually something
that might be workable?

--

---
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_509_55844961.1443811141440
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Last year, Herb Sutter proposed <a href=3D"http://www.open=
-std.org/jtc1/sc22/wg21/docs/papers/2014/n4074.pdf">N4074</a> (PDF), which =
allowed return statements to use direct-list-initialization rather than cop=
y-list-initialization rules. For those who don&#39;t recall, copy-list-init=
ialization says that, if a braced-init-list selects an `explicit` construct=
or, you get a compiler error.<br><br>I don&#39;t think I&#39;ve ever seen q=
uite so many papers written in response to a single proposal before. <a hre=
f=3D"http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4094.html">Th=
ree</a> <a href=3D"http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/=
n4131.html">separate</a> <a href=3D"http://www.open-std.org/JTC1/SC22/WG21/=
docs/papers/2014/n4223.html">papers</a> were written savaging the very idea=
 of the proposal. As such, it was quickly discarded.<br><br>However, there =
is still something there <i>in principle</i>. That something being the noti=
on that you should not have to type a typename more than once.<br><br>This =
is the idea behind auto return type deduction, after all. It allows you to =
just do this:<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">auto</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> func</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(.=
...)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><spa=
n style=3D"color: #606;" class=3D"styled-by-prettify">SomeType</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> blah</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">...</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">return</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> blah</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></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>The compiler figures out what you meant. =
`blah` has an explicit type, and that type (minus references) will be the r=
eturn value of the function. No problems.<br><br>Therefore, if you needed t=
o return something like a tuple, you&#39;d do this:<br><br><div class=3D"pr=
ettyprint" style=3D"background-color: rgb(250, 250, 250); border-color: rgb=
(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-w=
ord;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> func</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: #660;" clas=
s=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br>=C2=A0 </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">...</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> std</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">make_tu=
ple</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span style=3D"color: #066;" class=3D"styled-by-prettify">4</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: #066=
;" class=3D"styled-by-prettify">9.5f</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">}</span></div></code></div><br>And that all works.<br><br>Well,=
 it works right up until you&#39;re in a position where you <i>cannot</i> u=
se return type deduction. Not all functions are written in headers. And may=
be once modules come around, we&#39;ll be able to ignore return types outsi=
de of exceptional cases. But for today, you have to state an explicit type:=
<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"sub=
prettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify">std<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">tuple</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"col=
or: #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: #660;" class=3D"s=
tyled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> func</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">(...)</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">...</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">tuple</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">&lt;</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: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">float</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&gt;(</span><span style=3D"color: #066;" class=3D"styled-by-prettify">4</s=
pan><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">9.5f</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: #660;" class=
=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span></div></code></div><br>I hope I don&#39;t ever ha=
ve to change what this function returns. Otherwise, I&#39;d have to do it i=
n two places.<br><br>That being said, all of the reasons that have been sta=
ted for allowing `return {4, 9.5f}` to just &quot;work&quot; are still perf=
ectly valid. N4074 is the wrong solution.<br><br>That does not mean that it=
&#39;s not a problem worth solving.<br><br>All three response papers ultima=
tely cite one major problem: you&#39;ve <i>implicitly</i> broken the contra=
ct between the writer of the type and the user of the type. By declaring th=
at constructor `explicit`, the writer of the type said, &quot;I don&#39;t w=
ant implicit conversions to call this function.&quot; To therefore allow an=
 implicit conversion to do so would break the contract.<br><br>The user&#39=
;s problem with this is that he&#39;s already mentioned the typename once b=
efore; he shouldn&#39;t have to do it again.<br><br>So let&#39;s solve that=
 problem: give the user a way to perform explicit conversions <i>without</i=
> using the typename. For example:<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 clas=
s=3D"prettyprint"><div class=3D"subprettyprint"><span style=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"styl=
ed-by-prettify">tuple</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">&lt;</span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">int</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">float</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> func</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">(...)</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">...</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled=
-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>explicit</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><s=
pan style=3D"color: #066;" class=3D"styled-by-prettify">4</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">9.5f</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><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>There: problem solved. The user has expl=
icitly stated their desire for a conversion, thus satisfying the class writ=
er&#39;s contract. And the user doesn&#39;t have to use the typename in que=
stion; the compiler knows what it is.<br><br>Here&#39;s how an example from=
 N4094 would look and behave:<br><br><div class=3D"prettyprint" style=3D"ba=
ckground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); borde=
r-style: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"p=
rettyprint"><div class=3D"subprettyprint"><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">tuple</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify">seconds</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> nanoseconds</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r>test1</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: #660;" class=3D"styled-by-prettify">{</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">explicit</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #06=
6;" class=3D"styled-by-prettify">3</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: #066;" class=3D"styled-by-pret=
tify">4</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: #660;" class=3D"styled-by-prettify">}</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br><br>tuple</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">seconds</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> nanoseconds</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br>test2</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: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">explicit</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">{</span><span style=3D"color: #066;" class=3D"styled-by-prettify">3h</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">4ms</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">};</span><span style=3D"color: #000;" cl=
ass=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-b=
y-prettify"><br><br>tuple</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">&lt;</span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">int</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">float</span><spa=
n 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">string</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br>test3</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">e=
xplicit</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</=
span><span style=3D"color: #066;" class=3D"styled-by-prettify">3</span><spa=
n 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">4.5</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: #080;" class=3D"style=
d-by-prettify">&quot;text&quot;</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: #660;" class=3D"styled-by-pre=
ttify">}</span></div></code></div><br>We want test1 to be rejected, due to =
the inability to implicitly convert from integers to time units. But we wan=
t test2 and test3 to be accepted, since those types can be implicitly conve=
rted.<br><br>And this is how it ought to work.<br><br>However:<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-wr=
ap: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint">=
<span style=3D"color: #000;" class=3D"styled-by-prettify">tuple</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">seconds</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> nanoseconds</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br>test4</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: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">explicit</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">{</span><span style=3D"color: #008;" class=3D"styled-by-prettify">explici=
t</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><=
span style=3D"color: #066;" class=3D"styled-by-prettify">3</span><span styl=
e=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: #008;=
" class=3D"styled-by-prettify">explicit</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">{</span><span style=3D"color: #066;" class=3D"=
styled-by-prettify">4</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></div></code></div><br>This would also work. The two explicit-qualifi=
ed braced-init-lists do exact what they say: explicitly convert from an int=
eger to `seconds`.<br><br>What is to stop users from qualifying ever parame=
ter with `explicit`, thus rendering `explicit` constructors meaningless? Sy=
ntactic noise: nobody wants to read or write `explicit` that much. Just loo=
k at how noisy `test4` is compared to `test2`.<br><br>This should ensure th=
at it will be used <i>sparingly</i>.<br><br>Does this seem feasible, to <i>=
generally allow</i> (not just in return statements) `explicit` followed by =
braced-init-list to convert copy-list-initialization into direct-list-initi=
alization? Does putting a keyword there sufficient to satisfy the `explicit=
` contract on constructors?<br><br>Note that the feature would <i>only</i> =
work on braced-init-lists. So you couldn&#39;t do something like `explicit =
5`; you have to qualify it.<br><br><u><font size=3D"4">And then, something =
else occurred to me</font></u><br><br>A few years back, I was playing aroun=
d with some ideas about fixing the &quot;uniform initialization is not unif=
orm&quot; problem. That problem being that `vector&lt;int&gt;` hides severa=
l of its constructors from braced-init-lists, and therefore you cannot reli=
ably have `vector&lt;T&gt; t{5};` mean to actually call the constructor in =
template code.<br><br>I also remembered an early version of uniform initial=
ization which did indeed completely ignore the implicit/explicit distinctio=
n on constructors. That all braced-initialization was direct list initializ=
ation.<br><br>Well, if `explicit {}` is explicitly taking those back to tho=
se rules... why not have `explicit {}` <i>also</i> change the rules about w=
hat the `{}` actually means.<br><br>That is, create a third type of braced =
initialization: explicit-list-initialization. Such initialization looks exa=
ctly like direct-list-initialization, save for one change:<br><br>It <i>nev=
er</i> implicitly calls initializer_list constructors.<br><br>Therefore:<br=
><br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 25=
0); border-color: rgb(187, 187, 187); border-style: solid; border-width: 1p=
x; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subpre=
ttyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify">vector<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">T</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> t </span><span 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: #008;" class=3D"=
styled-by-prettify">explicit</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: #066;" class=3D"styled-by-prettify">=
5</span><span style=3D"color: #660;" class=3D"styled-by-prettify">};</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #800;" class=3D"styled-by-prettify">//Always calls the constru=
ctor taking a single integer argument.</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br>vector</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> t </span><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: #008;" class=3D"styled-by-prettify">explicit</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"co=
lor: #066;" class=3D"styled-by-prettify">5</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"style=
d-by-prettify">3</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: #066;" class=3D"styled-by-prettify">4</span><spa=
n 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: #066;" =
class=3D"styled-by-prettify">9</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettif=
y">//Always a compile error.</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br>vector</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">T</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> t =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">explicit</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: #066;"=
 class=3D"styled-by-prettify">5</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettif=
y">3</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #066;" class=3D"styled-by-prettify">4</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">-</span><span style=3D"color: #066;" class=3D"style=
d-by-prettify">9</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: #800;" class=3D"styled-by-prettify">//May atte=
mpt to call an initializer list constructor.</span></div></code></div><br>I=
 justify the use of `explicit` for this for one reason: pretty much <i>nobo=
dy</i> declares initializer list constructors `explicit`. They want you to =
use them by default, and you still can.<br><br>It&#39;s just that now, we h=
ave a way to call<br><br>This will also resolve some issues with allocator =
construct. That being the inability to initialize aggregates. `allocator::c=
onstruct` can be rewritten to (by default) use `explicit {std::forward&lt;A=
rgs&gt;(args)...}`. And you won&#39;t lose access to any constructors this =
way.<br><br>Any thoughts? Is this as insane as it sounds, or is this actual=
ly something that might be workable?<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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_509_55844961.1443811141440--
------=_Part_508_478071751.1443811141438--

.


Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Fri, 2 Oct 2015 14:52:32 -0400
Raw View
On Oct 2, 2015, at 2:39 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>=20
> tuple<seconds, nanoseconds>
> test1()
> {
>     return explicit{3, 4};
> }
>=20
> tuple<seconds, nanoseconds>
> test2()
> {
>     return explicit{3h, 4ms};
> }
>=20
> tuple<int, float, string>
> test3()
> {
>     return explicit{3, 4.5, "text"};
> }

The latest C++1z working draft (N4527) doesn=E2=80=99t compile test1() and =
does compile test2() and test3(), if you remove =E2=80=9Cexplicit=E2=80=9D =
in all three places:

tuple<seconds, nanoseconds>
test1()
{
    return {3, 4};
}

test.cpp:11:12: error: chosen constructor is explicit in copy-initializatio=
n
    return {3, 4};
           ^~~~~~

tuple<seconds, nanoseconds>
test2()
{
    return {3h, 4ms};  // ok
}

tuple<int, float, string>
test3()
{
    return {3, 4.5, "text=E2=80=9D};  // ok
}

I like this solution better.

Howard

--=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: Fri, 2 Oct 2015 12:52:03 -0700 (PDT)
Raw View
------=_Part_591_1736722271.1443815523940
Content-Type: multipart/alternative;
 boundary="----=_Part_592_460015239.1443815523940"

------=_Part_592_460015239.1443815523940
Content-Type: text/plain; charset=UTF-8

On Friday, October 2, 2015 at 2:52:36 PM UTC-4, Howard Hinnant wrote:
>
> On Oct 2, 2015, at 2:39 PM, Nicol Bolas <jmck...@gmail.com <javascript:>>
> wrote:
> I like this solution better.
>
> Howard
>

It's a solution that only works for tuple. And requires exceedingly
non-trivial SFINAE tricks to implement (or concepts). What about `variant`
(using N4542):

variant<int, float, std::string> func()
{
  return {emplaced_type_t<std::string>{}, "foo"};
}

That's a pretty gigantic expression as is; do I really have to expand it
with `variant<int, float, std::string>`? What happens when the type changes?

Or can I just do:

variant<int, float, std::string> func()
{
  return explicit {emplaced_type_t<std::string>{}, "foo"};
}

My suggestion works equally, for all types in all circumstances.

--

---
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_592_460015239.1443815523940
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Friday, October 2, 2015 at 2:52:36 PM UTC-4, Howard Hin=
nant wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Oct 2, 2015, at =
2:39 PM, Nicol Bolas &lt;<a href=3D"javascript:" target=3D"_blank" gdf-obfu=
scated-mailto=3D"1JjvLij4CgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D=
&#39;javascript:&#39;;return true;" onclick=3D"this.href=3D&#39;javascript:=
&#39;;return true;">jmck...@gmail.com</a>&gt; wrote:
<br>I like this solution better.
<br>
<br>Howard<br></blockquote><div><br>It&#39;s a solution that only works for=
 tuple. And requires exceedingly non-trivial SFINAE tricks to implement (or=
 concepts). What about `variant` (using N4542):<br><br><div class=3D"pretty=
print" 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">variant</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">&lt;</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: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">float</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">string</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> func</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify">em=
placed_type_t</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">&lt;</span><span style=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: #008;" class=3D"styled-by-prettify">string</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">&gt;{},</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #080;" class=3D"styled-by-prettify">&quot;foo&quot;</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">}</span></div></code></div><br>That&#39;s =
a pretty gigantic expression as is; do I really have to expand it with `var=
iant&lt;int, float, std::string&gt;`? What happens when the type changes?<b=
r><br>Or can I just do:<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: #000;" class=3D"s=
tyled-by-prettify">variant</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">&lt;</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"> std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">string</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> func</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">ret=
urn</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">explicit</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">emplaced_type_t</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=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: #008;" class=
=3D"styled-by-prettify">string</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">&gt;{},</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #080;" class=3D"styled-by-pr=
ettify">&quot;foo&quot;</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">};</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}=
</span></div></code></div><br>My suggestion works equally, for all types in=
 all circumstances.<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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_592_460015239.1443815523940--
------=_Part_591_1736722271.1443815523940--

.


Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Fri, 2 Oct 2015 15:57:25 -0400
Raw View
On Oct 2, 2015, at 3:52 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
>=20
> On Friday, October 2, 2015 at 2:52:36 PM UTC-4, Howard Hinnant wrote:
> On Oct 2, 2015, at 2:39 PM, Nicol Bolas <jmck...@gmail.com> wrote:=20
> I like this solution better.=20
>=20
> Howard
>=20
> It's a solution that only works for tuple. And requires exceedingly non-t=
rivial SFINAE tricks to implement (or concepts). What about `variant` (usin=
g N4542):
>=20
> variant<int, float, std::string> func()
> {
>   return {emplaced_type_t<std::string>{}, "foo"};
> }
>=20
> That's a pretty gigantic expression as is; do I really have to expand it =
with `variant<int, float, std::string>`? What happens when the type changes=
?
>=20
> Or can I just do:
>=20
> variant<int, float, std::string> func()
> {
>   return explicit {emplaced_type_t<std::string>{}, "foo"};
> }
>=20
> My suggestion works equally, for all types in all circumstances.

True enough.

I would love to see an easier way (possibly language supported) of implemen=
ting N4387=E2=80=99s "Perfect initialization=E2=80=9D.

Howard

--=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 Woehlke <mwoehlke.floss@gmail.com>
Date: Fri, 02 Oct 2015 16:32:06 -0400
Raw View
On 2015-10-02 14:39, Nicol Bolas wrote:
> Last year, Herb Sutter proposed N4074=20
> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4074.pdf> (PDF)=
,=20
> which allowed return statements to use direct-list-initialization rather=
=20
> than copy-list-initialization rules. For those who don't recall,=20
> copy-list-initialization says that, if a braced-init-list selects an=20
> `explicit` constructor, you get a compiler error.
>=20
> I don't think I've ever seen quite so many papers written in response to =
a=20
> single proposal before. Three=20
> <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4094.html>=20
> separate=20
> <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4131.html> pape=
rs=20
> <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4223.html> were=
=20
> written savaging the very idea of the proposal. As such, it was quickly=
=20
> discarded.
>=20
> All three response papers ultimately cite one major problem: you've=20
> *implicitly* broken the contract between the writer of the type and the=
=20
> user of the type. By declaring that constructor `explicit`, the writer of=
=20
> the type said, "I don't want implicit conversions to call this function."=
=20
> To therefore allow an implicit conversion to do so would break the contra=
ct.

I guess I don't mark my ctors 'explicit' often enough=C2=B9... I've always
"felt" that it is pretty clear if I use an untyped braced list as either
a function parameter or a return value, that obviously I mean the type
of said parameter/return. That doesn't seem to me like a case I should
have to rehash the typename.

(=C2=B9 Maybe I would if the compiler warned me when I forget. Which... mea=
ns
we'd need an "implicit"... Alas, I've mentioned that before, and it
wasn't received well enough to seem worth pursuing.)

> So let's solve that problem: give the user a way to perform explicit=20
> conversions *without* using the typename. For example:
>=20
> std::tuple<int, float> func(...)
> {
>   ...
>   return explicit {4, 9.5f};
> }

IMO that's a lame "solution"; I've still had to beat the compiler over
the head with the fact that I really, really want to construct an object
when it should have been obvious. (Put differently: what's the point of
return type elision if we turn around require the type name - or extra
syntax - anyway?)

Besides that if we had 'decltype(return)', you could as easily write
that as 'explicit', and it would be much more generally useful.

That said...

> tuple<seconds, nanoseconds>
> test4()
> {
>     return explicit{explicit{3}, explicit{4}};
> }

....*this* might be useful... maybe...

> Therefore:
>=20
> vector<T> t =3D explicit {5}; //Always calls the constructor taking a sin=
gle=20
> integer argument.
> vector<T> t =3D explicit {5, 3, 4, -9}; //Always a compile error.
> vector<T> t =3D explicit {{5, 3, 4, -9}}; //May attempt to call an=20
> initializer list constructor.

....or this, although tagged ctors seem like a better solution as they
are more descriptive.

--=20
Matthew

--=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: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Fri, 2 Oct 2015 14:35:58 -0700 (PDT)
Raw View
------=_Part_1265_1861045877.1443821758314
Content-Type: multipart/alternative;
 boundary="----=_Part_1266_2048641069.1443821758314"

------=_Part_1266_2048641069.1443821758314
Content-Type: text/plain; charset=UTF-8

On Friday, October 2, 2015 at 7:39:01 PM UTC+1, Nicol Bolas wrote:
>
> [...]
> The user's problem with this is that he's already mentioned the typename
> once before; he shouldn't have to do it again.
>
> So let's solve that problem: give the user a way to perform explicit
> conversions *without* using the typename. For example:
>
> std::tuple<int, float> func(...)
> {
>   ...
>   return explicit {4, 9.5f};
> }
>
> There: problem solved. The user has explicitly stated their desire for a
> conversion, thus satisfying the class writer's contract. And the user
> doesn't have to use the typename in question; the compiler knows what it is.
>
>
Excellent proposal.

This also solve another, IMHO more important, problem: returning
non-movable types with explicit constructors:

template<class M>
std::lock_guard<M> lock(M& m)
{
  return {m}; // invalid
  return explicit{m}; // ok!
}

-- gpd


--

---
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_1266_2048641069.1443821758314
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Friday, October 2, 2015 at 7:39:01 PM UTC+1, Nicol Bolas wrote:<blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">[...]<br>The user&#39;=
s problem with this is that he&#39;s already mentioned the typename once be=
fore; he shouldn&#39;t have to do it again.<br><br>So let&#39;s solve that =
problem: give the user a way to perform explicit conversions <i>without</i>=
 using the typename. For 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:#000">std</span>=
<span style=3D"color:#660">::</span><span style=3D"color:#000">tuple</span>=
<span style=3D"color:#660">&lt;</span><span style=3D"color:#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">&gt;</span><sp=
an style=3D"color:#000"> func</span><span style=3D"color:#660">(...)</span>=
<span style=3D"color:#000"><br></span><span style=3D"color:#660">{</span><s=
pan style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#660">...</=
span><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008=
">return</span><span style=3D"color:#000"> </span><span style=3D"color:#008=
">explicit</span><span style=3D"color:#000"> </span><span style=3D"color:#6=
60">{</span><span style=3D"color:#066">4</span><span style=3D"color:#660">,=
</span><span style=3D"color:#000"> </span><span style=3D"color:#066">9.5f</=
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></spa=
n></div></code></div><br>There: problem solved. The user has explicitly sta=
ted their desire for a conversion, thus satisfying the class writer&#39;s c=
ontract. And the user doesn&#39;t have to use the typename in question; the=
 compiler knows what it is.<br><br></div></blockquote><div><br>Excellent pr=
oposal.<br><br>This also solve another, IMHO more important, problem: retur=
ning non-movable types with explicit constructors:<br><br>template&lt;class=
 M&gt;<br>std::lock_guard&lt;M&gt; lock(M&amp; m)<br>{<br>=C2=A0 return {m}=
; // invalid<br>=C2=A0 return explicit{m}; // ok!<br>}<br><br>-- gpd<br><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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1266_2048641069.1443821758314--
------=_Part_1265_1861045877.1443821758314--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 2 Oct 2015 15:43:42 -0700 (PDT)
Raw View
------=_Part_1312_1004872427.1443825822901
Content-Type: multipart/alternative;
 boundary="----=_Part_1313_1679892952.1443825822902"

------=_Part_1313_1679892952.1443825822902
Content-Type: text/plain; charset=UTF-8

On Friday, October 2, 2015 at 4:32:28 PM UTC-4, Matthew Woehlke wrote:
>
> On 2015-10-02 14:39, Nicol Bolas wrote:
> > So let's solve that problem: give the user a way to perform explicit
> > conversions *without* using the typename. For example:
> >
> > std::tuple<int, float> func(...)
> > {
> >   ...
> >   return explicit {4, 9.5f};
> > }
>
> IMO that's a lame "solution";


I can't say I entirely disagree. But considering the sheer *vehemence* of
the response to N4074, this is probably the best you can expect to see.

That's not to say that I don't understand those concerns. But they're
strongly held and those people seem to be ready to fight tooth and nail to
prevent `return {}` from using explicit constructors.


> That said...
>
> > tuple<seconds, nanoseconds>
> > test4()
> > {
> >     return explicit{explicit{3}, explicit{4}};
> > }
>
> ...*this* might be useful... maybe...
>
> > Therefore:
> >
> > vector<T> t = explicit {5}; //Always calls the constructor taking a
> single
> > integer argument.
> > vector<T> t = explicit {5, 3, 4, -9}; //Always a compile error.
> > vector<T> t = explicit {{5, 3, 4, -9}}; //May attempt to call an
> > initializer list constructor.
>
> ...or this, although tagged ctors seem like a better solution as they
> are more descriptive.
>

Yeah, I've heard the whole "use tagged constructors" stuff. And there's one
titanic stumbling block with that:

There is *not one C++ standard library type* that both has initializer_list
constructors and use tagged constructors to disambiguate them. Not a single
one.

I don't care if this is for legacy reasons. That's what people see, have to
deal with, and will copy from. You can shout about tagged constructors from
rooftops, and it will change nothing.

The only way to actually fix this is at the source: to allow users to
disambiguate braced-init-lists.

--

---
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_1313_1679892952.1443825822902
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Friday, October 2, 2015 at 4:32:28 PM UTC-4, Matthew Wo=
ehlke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 2015-10-02 14:3=
9, Nicol Bolas wrote:
<br>&gt; So let&#39;s solve that problem: give the user a way to perform ex=
plicit=20
<br>&gt; conversions *without* using the typename. For example:
<br>&gt;=20
<br>&gt; std::tuple&lt;int, float&gt; func(...)
<br>&gt; {
<br>&gt; =C2=A0 ...
<br>&gt; =C2=A0 return explicit {4, 9.5f};
<br>&gt; }
<br>
<br>IMO that&#39;s a lame &quot;solution&quot;;</blockquote><div><br>I can&=
#39;t say I entirely disagree. But considering the sheer <i>vehemence</i> o=
f the response to N4074, this is probably the best you can expect to see.<b=
r><br>That&#39;s not to say that I don&#39;t understand those concerns. But=
 they&#39;re strongly held and those people seem to be ready to fight tooth=
 and nail to prevent `return {}` from using explicit constructors.<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;">That said...
<br>
<br>&gt; tuple&lt;seconds, nanoseconds&gt;
<br>&gt; test4()
<br>&gt; {
<br>&gt; =C2=A0 =C2=A0 return explicit{explicit{3}, explicit{4}};
<br>&gt; }
<br>
<br>...*this* might be useful... maybe...
<br>
<br>&gt; Therefore:
<br>&gt;=20
<br>&gt; vector&lt;T&gt; t =3D explicit {5}; //Always calls the constructor=
 taking a single=20
<br>&gt; integer argument.
<br>&gt; vector&lt;T&gt; t =3D explicit {5, 3, 4, -9}; //Always a compile e=
rror.
<br>&gt; vector&lt;T&gt; t =3D explicit {{5, 3, 4, -9}}; //May attempt to c=
all an=20
<br>&gt; initializer list constructor.
<br>
<br>...or this, although tagged ctors seem like a better solution as they
<br>are more descriptive.<br></blockquote><div><br></div>Yeah, I&#39;ve hea=
rd the whole &quot;use tagged constructors&quot; stuff. And there&#39;s one=
 titanic stumbling block with that:<br><br>There is <b>not one C++ standard=
 library type</b> that both has initializer_list constructors and use tagge=
d constructors to disambiguate them. Not a single one.<br><br>I don&#39;t c=
are if this is for legacy reasons. That&#39;s what people see, have to deal=
 with, and will copy from. You can shout about tagged constructors from roo=
ftops, and it will change nothing.<br><br>The only way to actually fix this=
 is at the source: to allow users to disambiguate braced-init-lists.<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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1313_1679892952.1443825822902--
------=_Part_1312_1004872427.1443825822901--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 2 Oct 2015 19:05:40 -0700 (PDT)
Raw View
------=_Part_1436_181926179.1443837940251
Content-Type: multipart/alternative;
 boundary="----=_Part_1437_133993795.1443837940251"

------=_Part_1437_133993795.1443837940251
Content-Type: text/plain; charset=UTF-8

On Friday, October 2, 2015 at 5:35:58 PM UTC-4, Giovanni Piero Deretta
wrote:
>
> On Friday, October 2, 2015 at 7:39:01 PM UTC+1, Nicol Bolas wrote:
>>
>> [...]
>> The user's problem with this is that he's already mentioned the typename
>> once before; he shouldn't have to do it again.
>>
>> So let's solve that problem: give the user a way to perform explicit
>> conversions *without* using the typename. For example:
>>
>> std::tuple<int, float> func(...)
>> {
>>   ...
>>   return explicit {4, 9.5f};
>> }
>>
>> There: problem solved. The user has explicitly stated their desire for a
>> conversion, thus satisfying the class writer's contract. And the user
>> doesn't have to use the typename in question; the compiler knows what it is.
>>
>>
> Excellent proposal.
>
> This also solve another, IMHO more important, problem: returning
> non-movable types with explicit constructors:
>
> template<class M>
> std::lock_guard<M> lock(M& m)
> {
>   return {m}; // invalid
>   return explicit{m}; // ok!
> }
>
> -- gpd
>
>
>
I don't see how that's valid regardless of whether the constructor is
implicit or explicit. The reason you can't return immobile values is
because the other end has to do `auto x = lock(m);` And while virtually any
compiler worth its salt will not call the move constructor, the C++
standard *requires* that it be available to be called. Because compilers
are only permitted the option of ignoring the call; they're not required to
do so.

Granted, there's a proposal to resolve that issue
<http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0135r0.html>. But
if that goes through, it should allow `return lock_guard<M>(m);` to be
exactly equivalent to `return lock_guard<M>{m};`.

--

---
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_1437_133993795.1443837940251
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Friday, October 2, 2015 at 5:35:58 PM UTC-4, Giovanni Piero Deretta wrot=
e:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;">On Friday, October 2, 2015 a=
t 7:39:01 PM UTC+1, Nicol Bolas wrote:<blockquote class=3D"gmail_quote" sty=
le=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1e=
x"><div dir=3D"ltr">[...]<br>The user&#39;s problem with this is that he&#3=
9;s already mentioned the typename once before; he shouldn&#39;t have to do=
 it again.<br><br>So let&#39;s solve that problem: give the user a way to p=
erform explicit conversions <i>without</i> using the typename. For example:=
<br><br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(18=
7,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><code>=
<div><span style=3D"color:#000">std</span><span style=3D"color:#660">::</sp=
an><span style=3D"color:#000">tuple</span><span style=3D"color:#660">&lt;</=
span><span style=3D"color:#008">int</span><span style=3D"color:#660">,</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#008">float</span=
><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"> func</sp=
an><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>=C2=
=A0 </span><span style=3D"color:#660">...</span><span style=3D"color:#000">=
<br>=C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#008">explicit</span><span style=3D"=
color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color=
:#066">4</span><span style=3D"color:#660">,</span><span style=3D"color:#000=
"> </span><span style=3D"color:#066">9.5f</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></span></div></code></div><br>There: =
problem solved. The user has explicitly stated their desire for a conversio=
n, thus satisfying the class writer&#39;s contract. And the user doesn&#39;=
t have to use the typename in question; the compiler knows what it is.<br><=
br></div></blockquote><div><br>Excellent proposal.<br><br>This also solve a=
nother, IMHO more important, problem: returning non-movable types with expl=
icit constructors:<br><br>template&lt;class M&gt;<br>std::lock_guard&lt;M&g=
t; lock(M&amp; m)<br>{<br>=C2=A0 return {m}; // invalid<br>=C2=A0 return ex=
plicit{m}; // ok!<br>}<br><br>-- gpd<br><br><br></div></blockquote><div><br=
>I don&#39;t see how that&#39;s valid regardless of whether the constructor=
 is implicit or explicit. The reason you can&#39;t return immobile values i=
s because the other end has to do `auto x =3D lock(m);` And while virtually=
 any compiler worth its salt will not call the move constructor, the C++ st=
andard <i>requires</i> that it be available to be called. Because compilers=
 are only permitted the option of ignoring the call; they&#39;re not requir=
ed to do so.<br><br>Granted, there&#39;s a <a href=3D"http://www.open-std.o=
rg/JTC1/SC22/WG21/docs/papers/2015/p0135r0.html">proposal to resolve that i=
ssue</a>. But if that goes through, it should allow `return lock_guard&lt;M=
&gt;(m);` to be exactly equivalent to `return lock_guard&lt;M&gt;{m};`.<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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1437_133993795.1443837940251--
------=_Part_1436_181926179.1443837940251--

.


Author: Shahms King <shahms.king@gmail.com>
Date: Sat, 03 Oct 2015 18:53:38 +0000
Raw View
--001a113da7c8de97e8052137cc84
Content-Type: text/plain; charset=UTF-8

On Fri, Oct 2, 2015 at 7:05 PM Nicol Bolas <jmckesson@gmail.com> wrote:

> On Friday, October 2, 2015 at 5:35:58 PM UTC-4, Giovanni Piero Deretta
> wrote:
>>
>> On Friday, October 2, 2015 at 7:39:01 PM UTC+1, Nicol Bolas wrote:
>>>
>>> [...]
>>> The user's problem with this is that he's already mentioned the typename
>>> once before; he shouldn't have to do it again.
>>>
>>> So let's solve that problem: give the user a way to perform explicit
>>> conversions *without* using the typename. For example:
>>>
>>> std::tuple<int, float> func(...)
>>> {
>>>   ...
>>>   return explicit {4, 9.5f};
>>> }
>>>
>>> There: problem solved. The user has explicitly stated their desire for a
>>> conversion, thus satisfying the class writer's contract. And the user
>>> doesn't have to use the typename in question; the compiler knows what it is.
>>>
>>>
>> Excellent proposal.
>>
>> This also solve another, IMHO more important, problem: returning
>> non-movable types with explicit constructors:
>>
>> template<class M>
>> std::lock_guard<M> lock(M& m)
>> {
>>   return {m}; // invalid
>>   return explicit{m}; // ok!
>> }
>>
>> -- gpd
>>
>>
>>
> I don't see how that's valid regardless of whether the constructor is
> implicit or explicit. The reason you can't return immobile values is
> because the other end has to do `auto x = lock(m);` And while virtually any
> compiler worth its salt will not call the move constructor, the C++
> standard *requires* that it be available to be called. Because compilers
> are only permitted the option of ignoring the call; they're not required to
> do so.
>

It is legal right now to return a immovable object with an implicit
constructor using a braced-init-list.  You cannot capture the return
by-value in the caller, however.

struct Immovable {
  Immovable() = default;
  Immovable(const Immovable&) = delete;
  Immovable(Immovable&&) = delete;
};

Immovable make() {
  return {};
}

auto&& wtf = make();

(That being said, I do hope P0135 is accepted in some form).

--Shahms


>
> Granted, there's a proposal to resolve that issue
> <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0135r0.html>.
> But if that goes through, it should allow `return lock_guard<M>(m);` to be
> exactly equivalent to `return lock_guard<M>{m};`.
>
> --
>
> ---
> 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/.
>

--

---
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/.

--001a113da7c8de97e8052137cc84
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_quote"><div dir=3D"ltr">On Fri, Oct 2,=
 2015 at 7:05 PM Nicol Bolas &lt;<a href=3D"mailto:jmckesson@gmail.com">jmc=
kesson@gmail.com</a>&gt; wrote:<br></div><blockquote class=3D"gmail_quote" =
style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On =
Friday, October 2, 2015 at 5:35:58 PM UTC-4, Giovanni Piero Deretta wrote:<=
blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border=
-left:1px #ccc solid;padding-left:1ex">On Friday, October 2, 2015 at 7:39:0=
1 PM UTC+1, Nicol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div =
dir=3D"ltr">[...]<br>The user&#39;s problem with this is that he&#39;s alre=
ady mentioned the typename once before; he shouldn&#39;t have to do it agai=
n.<br><br>So let&#39;s solve that problem: give the user a way to perform e=
xplicit conversions <i>without</i> using the typename. For example:<br><br>=
<div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,18=
7);border-style:solid;border-width:1px;word-wrap:break-word"><code><div><sp=
an style=3D"color:#000">std</span><span style=3D"color:#660">::</span><span=
 style=3D"color:#000">tuple</span><span style=3D"color:#660">&lt;</span><sp=
an style=3D"color:#008">int</span><span style=3D"color:#660">,</span><span =
style=3D"color:#000"> </span><span style=3D"color:#008">float</span><span s=
tyle=3D"color:#660">&gt;</span><span style=3D"color:#000"> func</span><span=
 style=3D"color:#660">(...)</span><span style=3D"color:#000"><br></span><sp=
an style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </spa=
n><span style=3D"color:#660">...</span><span style=3D"color:#000"><br>=C2=
=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#008">explicit</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#066">=
4</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#066">9.5f</span><span style=3D"color:#660">};</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#660">}</span>=
<span style=3D"color:#000"><br></span></div></code></div><br>There: problem=
 solved. The user has explicitly stated their desire for a conversion, thus=
 satisfying the class writer&#39;s contract. And the user doesn&#39;t have =
to use the typename in question; the compiler knows what it is.<br><br></di=
v></blockquote><div><br>Excellent proposal.<br><br>This also solve another,=
 IMHO more important, problem: returning non-movable types with explicit co=
nstructors:<br><br>template&lt;class M&gt;<br>std::lock_guard&lt;M&gt; lock=
(M&amp; m)<br>{<br>=C2=A0 return {m}; // invalid<br>=C2=A0 return explicit{=
m}; // ok!<br>}<br><br>-- gpd<br><br><br></div></blockquote><div><br>I don&=
#39;t see how that&#39;s valid regardless of whether the constructor is imp=
licit or explicit. The reason you can&#39;t return immobile values is becau=
se the other end has to do `auto x =3D lock(m);` And while virtually any co=
mpiler worth its salt will not call the move constructor, the C++ standard =
<i>requires</i> that it be available to be called. Because compilers are on=
ly permitted the option of ignoring the call; they&#39;re not required to d=
o so.<br></div></blockquote><div><br></div><div>It is legal right now to re=
turn a immovable object with an implicit constructor using a braced-init-li=
st.=C2=A0 You cannot capture the return by-value in the caller, however.</d=
iv><div><br></div><div>struct Immovable {</div><div>=C2=A0 Immovable() =3D =
default;</div><div>=C2=A0 Immovable(const Immovable&amp;) =3D delete;</div>=
<div>=C2=A0 Immovable(Immovable&amp;&amp;) =3D delete;</div><div>};</div><d=
iv><br></div><div>Immovable make() {</div><div>=C2=A0 return {};</div><div>=
}</div><div><br></div><div>auto&amp;&amp; wtf =3D make();</div><div><br></d=
iv><div>(That being said, I do hope P0135 is accepted in some form).</div><=
div><br></div><div>--Shahms</div><div>=C2=A0</div><blockquote class=3D"gmai=
l_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left=
:1ex"><div><br>Granted, there&#39;s a <a href=3D"http://www.open-std.org/JT=
C1/SC22/WG21/docs/papers/2015/p0135r0.html" target=3D"_blank">proposal to r=
esolve that issue</a>. But if that goes through, it should allow `return lo=
ck_guard&lt;M&gt;(m);` to be exactly equivalent to `return lock_guard&lt;M&=
gt;{m};`.<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&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</blockquote></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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--001a113da7c8de97e8052137cc84--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 3 Oct 2015 13:37:47 -0700 (PDT)
Raw View
------=_Part_2086_638883834.1443904668034
Content-Type: multipart/alternative;
 boundary="----=_Part_2087_661384545.1443904668035"

------=_Part_2087_661384545.1443904668035
Content-Type: text/plain; charset=UTF-8



On Saturday, October 3, 2015 at 2:53:49 PM UTC-4, Shahms King wrote:
>
> On Fri, Oct 2, 2015 at 7:05 PM Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> On Friday, October 2, 2015 at 5:35:58 PM UTC-4, Giovanni Piero Deretta
>> wrote:
>>>
>>> On Friday, October 2, 2015 at 7:39:01 PM UTC+1, Nicol Bolas wrote:
>>>>
>>>> [...]
>>>> The user's problem with this is that he's already mentioned the
>>>> typename once before; he shouldn't have to do it again.
>>>>
>>>> So let's solve that problem: give the user a way to perform explicit
>>>> conversions *without* using the typename. For example:
>>>>
>>>> std::tuple<int, float> func(...)
>>>> {
>>>>   ...
>>>>   return explicit {4, 9.5f};
>>>> }
>>>>
>>>> There: problem solved. The user has explicitly stated their desire for
>>>> a conversion, thus satisfying the class writer's contract. And the user
>>>> doesn't have to use the typename in question; the compiler knows what it is.
>>>>
>>>>
>>> Excellent proposal.
>>>
>>> This also solve another, IMHO more important, problem: returning
>>> non-movable types with explicit constructors:
>>>
>>> template<class M>
>>> std::lock_guard<M> lock(M& m)
>>> {
>>>   return {m}; // invalid
>>>   return explicit{m}; // ok!
>>> }
>>>
>>> -- gpd
>>>
>>>
>>>
>> I don't see how that's valid regardless of whether the constructor is
>> implicit or explicit. The reason you can't return immobile values is
>> because the other end has to do `auto x = lock(m);` And while virtually any
>> compiler worth its salt will not call the move constructor, the C++
>> standard *requires* that it be available to be called. Because compilers
>> are only permitted the option of ignoring the call; they're not required to
>> do so.
>>
>
> It is legal right now to return a immovable object with an implicit
> constructor using a braced-init-list.  You cannot capture the return
> by-value in the caller, however.
>

Hmm. I want to make sure I understand where the current limits are.

You're saying that, given your definition of `Immobile`, it would be
illegal to do `return Immobile();`. However, it is legal to do `return {};`.

So... is it legal to do `return Immobile{};`?

--

---
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_2087_661384545.1443904668035
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<br><br>On Saturday, October 3, 2015 at 2:53:49 PM UTC-4, Shahms King wrote=
:<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"><div class=
=3D"gmail_quote"><div dir=3D"ltr">On Fri, Oct 2, 2015 at 7:05 PM Nicol Bola=
s &lt;<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"ej=
4O081GCwAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;javascript:&#3=
9;;return true;" onclick=3D"this.href=3D&#39;javascript:&#39;;return true;"=
>jmck...@gmail.com</a>&gt; wrote:<br></div><blockquote class=3D"gmail_quote=
" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">O=
n Friday, October 2, 2015 at 5:35:58 PM UTC-4, Giovanni Piero Deretta wrote=
:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bord=
er-left:1px #ccc solid;padding-left:1ex">On Friday, October 2, 2015 at 7:39=
:01 PM UTC+1, Nicol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"=
margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><di=
v dir=3D"ltr">[...]<br>The user&#39;s problem with this is that he&#39;s al=
ready mentioned the typename once before; he shouldn&#39;t have to do it ag=
ain.<br><br>So let&#39;s solve that problem: give the user a way to perform=
 explicit conversions <i>without</i> using the typename. For example:<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:#000">std</span><span style=3D"color:#660">::</span><sp=
an style=3D"color:#000">tuple</span><span style=3D"color:#660">&lt;</span><=
span style=3D"color:#008">int</span><span style=3D"color:#660">,</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#008">float</span><span=
 style=3D"color:#660">&gt;</span><span style=3D"color:#000"> func</span><sp=
an style=3D"color:#660">(...)</span><span style=3D"color:#000"><br></span><=
span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </s=
pan><span style=3D"color:#660">...</span><span style=3D"color:#000"><br>=C2=
=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#008">explicit</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#066">=
4</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#066">9.5f</span><span style=3D"color:#660">};</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#660">}</span>=
<span style=3D"color:#000"><br></span></div></code></div><br>There: problem=
 solved. The user has explicitly stated their desire for a conversion, thus=
 satisfying the class writer&#39;s contract. And the user doesn&#39;t have =
to use the typename in question; the compiler knows what it is.<br><br></di=
v></blockquote><div><br>Excellent proposal.<br><br>This also solve another,=
 IMHO more important, problem: returning non-movable types with explicit co=
nstructors:<br><br>template&lt;class M&gt;<br>std::lock_guard&lt;M&gt; lock=
(M&amp; m)<br>{<br>=C2=A0 return {m}; // invalid<br>=C2=A0 return explicit{=
m}; // ok!<br>}<br><br>-- gpd<br><br><br></div></blockquote><div><br>I don&=
#39;t see how that&#39;s valid regardless of whether the constructor is imp=
licit or explicit. The reason you can&#39;t return immobile values is becau=
se the other end has to do `auto x =3D lock(m);` And while virtually any co=
mpiler worth its salt will not call the move constructor, the C++ standard =
<i>requires</i> that it be available to be called. Because compilers are on=
ly permitted the option of ignoring the call; they&#39;re not required to d=
o so.<br></div></blockquote><div><br></div><div>It is legal right now to re=
turn a immovable object with an implicit constructor using a braced-init-li=
st.=C2=A0 You cannot capture the return by-value in the caller, however.</d=
iv></div></div></blockquote><div><br>Hmm. I want to make sure I understand =
where the current limits are.<br><br>You&#39;re saying that, given your def=
inition of `Immobile`, it would be illegal to do `return Immobile();`. Howe=
ver, it is legal to do `return {};`.<br><br>So... is it legal to do `return=
 Immobile{};`?</div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_2087_661384545.1443904668035--
------=_Part_2086_638883834.1443904668034--

.


Author: David Krauss <potswa@gmail.com>
Date: Sun, 4 Oct 2015 07:39:58 +0800
Raw View
--Apple-Mail=_AD5D42E6-4E6C-4E96-8EA6-CEEABB3348BB
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8


> On 2015=E2=80=9310=E2=80=9304, at 4:37 AM, Nicol Bolas <jmckesson@gmail.c=
om> wrote:
>=20
> So... is it legal to do `return Immobile{};`?

Nope. The only currently legal way is to return the braced-init-list (not a=
 prvalue expression) and to bind the return value to a reference.

--=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=_AD5D42E6-4E6C-4E96-8EA6-CEEABB3348BB
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 2015=E2=80=9310=
=E2=80=9304, at 4:37 AM, Nicol Bolas &lt;<a href=3D"mailto:jmckesson@gmail.=
com" class=3D"">jmckesson@gmail.com</a>&gt; wrote:</div><br class=3D"Apple-=
interchange-newline"><div class=3D""><span style=3D"font-family: Helvetica;=
 font-size: 12px; font-style: normal; font-variant: normal; font-weight: no=
rmal; letter-spacing: normal; line-height: normal; orphans: auto; text-alig=
n: start; text-indent: 0px; text-transform: none; white-space: normal; wido=
ws: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; d=
isplay: inline !important;" class=3D"">So... is it legal to do `return Immo=
bile{};`?</span></div></blockquote></div><br class=3D""><div class=3D"">Nop=
e. The only currently legal way is to <font face=3D"Courier" class=3D"">ret=
urn</font> the <i class=3D"">braced-init-list</i> (not a prvalue expression=
) and to bind the return value to a reference.</div><div class=3D""><br cla=
ss=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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--Apple-Mail=_AD5D42E6-4E6C-4E96-8EA6-CEEABB3348BB--

.