Topic: More uniform initialization
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 12 Nov 2012 16:50:02 -0800 (PST)
Raw View
------=_Part_141_4767680.1352767802572
Content-Type: text/plain; charset=ISO-8859-1
Currently, uniform initialization allows you to use {} in virtually all
cases of initialization. But not all.
Consider:
std::vector<int> intVec1( 43 );
std::vector<int> intVec2{ 43 };
Do these do the same thing? No. `intVec1` will be a vector containing 43
value-initialized integers. `intVec2` will be a vector containing a single
integer who's value is 43.
This happens because an initializer_list constructor, when it fits the
braced-init-list, takes priority when determining which constructors to
call. That's a problem.
Now it's important to note that this is only a problem because the type of
the vector matches the type used for the sizing constructor. Fixing this in
the language is not going to be possible; a much better fix is to provide
library support. For example:
std::vector<int> intVec1( 43, std::value_init );
std::vector<int> intVec2{ 43, std::value_init };
The constructor of `std::vector` that takes a single integer could be
extended to take an integer and a default parameter value of type
`std::value_init_t`. And `std::value_init` would be a value of that type.
The only way this initialization would be non-uniform is if you tried to
initialize a `vector<std::value_init_t>`s.
I think we can live with that.
The proposal would be to go through each templated standard library type
that has an initializer_list constructor and see when it could conflict
with other constructors. In those cases, add a default parameter of some
standard library type to disambiguate it.
--
------=_Part_141_4767680.1352767802572
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Currently, uniform initialization allows you to use {} in virtually all cas=
es of initialization. But not all.<br><br>Consider:<br><br>std::vector<i=
nt> intVec1( 43 );<br>std::vector<int> intVec2{ 43 };<br><br>Do th=
ese do the same thing? No. `intVec1` will be a vector containing 43 value-i=
nitialized integers. `intVec2` will be a vector containing a single integer=
who's value is 43.<br><br>This happens because an initializer_list constru=
ctor, when it fits the braced-init-list, takes priority when determining wh=
ich constructors to call. That's a problem.<br><br>Now it's important to no=
te that this is only a problem because the type of the vector matches the t=
ype used for the sizing constructor. Fixing this in the language is not goi=
ng to be possible; a much better fix is to provide library support. For exa=
mple:<br><br>std::vector<int> intVec1( 43, std::value_init );<br>std:=
:vector<int> intVec2{ 43, std::value_init };<br><br>The constructor o=
f `std::vector` that takes a single integer could be extended to take an in=
teger and a default parameter value of type `std::value_init_t`. And `std::=
value_init` would be a value of that type. The only way this initialization=
would be non-uniform is if you tried to initialize a `vector<std::value=
_init_t>`s.<br><br>I think we can live with that.<br><br>The proposal wo=
uld be to go through each templated standard library type that has an initi=
alizer_list constructor and see when it could conflict with other construct=
ors. In those cases, add a default parameter of some standard library type =
to disambiguate it.<br>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_141_4767680.1352767802572--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Mon, 12 Nov 2012 19:49:57 -0600
Raw View
--0015174c454e085c7604ce56a563
Content-Type: text/plain; charset=ISO-8859-1
On 12 November 2012 18:50, Nicol Bolas <jmckesson@gmail.com> wrote:
> The constructor of `std::vector` that takes a single integer could be
> extended to take an integer and a default parameter value of type
> `std::value_init_t`. And `std::value_init` would be a value of that type.
> The only way this initialization would be non-uniform is if you tried to
> initialize a `vector<std::value_init_t>`s.
>
Making value_init_t a nested type inside the container would take care of
that case as well.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
--0015174c454e085c7604ce56a563
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On 12 November 2012 18:50, Nicol Bolas <span dir=3D"ltr"><<a href=3D"mai=
lto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></spa=
n> wrote:<br><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
The constructor of `std::vector` that takes a single integer could be exten=
ded to take an integer and a default parameter value of type `std::value_in=
it_t`. And `std::value_init` would be a value of that type. The only way th=
is initialization would be non-uniform is if you tried to initialize a `vec=
tor<std::value_init_t>`s.<br>
</blockquote><div><br></div><div>Making value_init_t a nested type inside t=
he container would take care of that case as well.</div></div>-- <br>=A0Nev=
in ":-)" Liber=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord=
..com" target=3D"_blank">nevin@eviloverlord.com</a>>=A0 (847) 691-1404<br=
>
<p></p>
-- <br />
<br />
<br />
<br />
--0015174c454e085c7604ce56a563--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 12 Nov 2012 17:52:35 -0800 (PST)
Raw View
------=_Part_160_6482971.1352771555893
Content-Type: text/plain; charset=ISO-8859-1
On Monday, November 12, 2012 5:50:40 PM UTC-8, Nevin ":-)" Liber wrote:
>
> On 12 November 2012 18:50, Nicol Bolas <jmck...@gmail.com <javascript:>>wrote:
>
>> The constructor of `std::vector` that takes a single integer could be
>> extended to take an integer and a default parameter value of type
>> `std::value_init_t`. And `std::value_init` would be a value of that type.
>> The only way this initialization would be non-uniform is if you tried to
>> initialize a `vector<std::value_init_t>`s.
>>
>
> Making value_init_t a nested type inside the container would take care of
> that case as well.
> --
> Nevin ":-)" Liber <mailto:ne...@eviloverlord.com <javascript:>> (847)
> 691-1404
>
Perhaps, but you also wouldn't be able to declare a single
std::value_init_t, since it would change with each class template. And
therefore, you couldn't define a global std::value_init value to use.
--
------=_Part_160_6482971.1352771555893
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, November 12, 2012 5:50:40 PM UTC-8, Nevin ":-)" Liber wr=
ote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex=
;border-left: 1px #ccc solid;padding-left: 1ex;">On 12 November 2012 18:50,=
Nicol Bolas <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank=
" gdf-obfuscated-mailto=3D"Oi6cZaSi47wJ">jmck...@gmail.com</a>></span> w=
rote:<br><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
The constructor of `std::vector` that takes a single integer could be exten=
ded to take an integer and a default parameter value of type `std::value_in=
it_t`. And `std::value_init` would be a value of that type. The only way th=
is initialization would be non-uniform is if you tried to initialize a `vec=
tor<std::value_init_t>`s.<br>
</blockquote><div><br></div><div>Making value_init_t a nested type inside t=
he container would take care of that case as well.</div></div>-- <br> =
Nevin ":-)" Liber <mailto:<a href=3D"javascript:" target=3D"_blank=
" gdf-obfuscated-mailto=3D"Oi6cZaSi47wJ">ne...@eviloverlord.com</a><wbr>>=
; (847) 691-1404<br></blockquote><div><br>Perhaps, but you also would=
n't be able to declare a single std::value_init_t, since it would change wi=
th each class template. And therefore, you couldn't define a global std::va=
lue_init value to use.<br></div>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_160_6482971.1352771555893--
.
Author: Arthur Tchaikovsky <atch.cpp@gmail.com>
Date: Mon, 12 Nov 2012 22:57:14 -0800 (PST)
Raw View
------=_Part_1923_15375994.1352789834073
Content-Type: text/plain; charset=ISO-8859-1
Nicol
So with your proposal how would I go about initializing vector - the
simplest/most common case, I want vector of ints and I want some values in
it, would that be sufficient:
vector<int> v{1,2,3};
On Tuesday, 13 November 2012 01:52:36 UTC, Nicol Bolas wrote:
>
>
>
> On Monday, November 12, 2012 5:50:40 PM UTC-8, Nevin ":-)" Liber wrote:
>>
>> On 12 November 2012 18:50, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>> The constructor of `std::vector` that takes a single integer could be
>>> extended to take an integer and a default parameter value of type
>>> `std::value_init_t`. And `std::value_init` would be a value of that type.
>>> The only way this initialization would be non-uniform is if you tried to
>>> initialize a `vector<std::value_init_t>`s.
>>>
>>
>> Making value_init_t a nested type inside the container would take care of
>> that case as well.
>> --
>> Nevin ":-)" Liber <mailto:ne...@eviloverlord.com> (847) 691-1404
>>
>
> Perhaps, but you also wouldn't be able to declare a single
> std::value_init_t, since it would change with each class template. And
> therefore, you couldn't define a global std::value_init value to use.
>
--
------=_Part_1923_15375994.1352789834073
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div>Nicol<br></div><div><br></div><div>So with your proposal how would I g=
o about initializing vector - the simplest/most common case, I want vector =
of ints and I want some values in it, would that be sufficient:</div><div><=
br></div><div>vector<int> v{1,2,3};<br></div><div><br></div>On Tuesda=
y, 13 November 2012 01:52:36 UTC, Nicol Bolas wrote:<blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;padding-left: 1ex;"><br><br>On Monday, November 12, 2012 5:50:40 PM UTC-=
8, Nevin ":-)" Liber wrote:<blockquote class=3D"gmail_quote" style=3D"margi=
n:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">On 12 No=
vember 2012 18:50, Nicol Bolas <span dir=3D"ltr"><<a>jmck...@gmail.com</=
a>></span> wrote:<br><div class=3D"gmail_quote"><blockquote class=3D"gma=
il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef=
t:1ex">
The constructor of `std::vector` that takes a single integer could be exten=
ded to take an integer and a default parameter value of type `std::value_in=
it_t`. And `std::value_init` would be a value of that type. The only way th=
is initialization would be non-uniform is if you tried to initialize a `vec=
tor<std::value_init_t>`s.<br>
</blockquote><div><br></div><div>Making value_init_t a nested type inside t=
he container would take care of that case as well.</div></div>-- <br> =
Nevin ":-)" Liber <mailto:<a>ne...@eviloverlord.com</a>> =
(847) 691-1404<br></blockquote><div><br>Perhaps, but you also wouldn't be a=
ble to declare a single std::value_init_t, since it would change with each =
class template. And therefore, you couldn't define a global std::value_init=
value to use.<br></div></blockquote>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_1923_15375994.1352789834073--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 13 Nov 2012 01:22:26 -0600
Raw View
--0015174c0bfc0f4bf204ce5b4ae2
Content-Type: text/plain; charset=ISO-8859-1
On 12 November 2012 19:52, Nicol Bolas <jmckesson@gmail.com> wrote:
> Making value_init_t a nested type inside the container would take care of
>> that case as well.
>> --
>> Nevin ":-)" Liber <mailto:ne...@eviloverlord.com**> (847) 691-1404
>>
>
> Perhaps, but you also wouldn't be able to declare a single
> std::value_init_t, since it would change with each class template. And
> therefore, you couldn't define a global std::value_init value to use.
>
Agreed. There are, of course, advantages to this, such as easier to use in
generic code working with member initializers.
However, this is a small feature I would like to see in C++14 (actually,
the one I really want to see is default_init_t, but the same argument
applies), and I believe the impact of std::default_init_t may end up
pushing it to C++17 for the following reasons:
1. It will take time to nail down what is meant by
vector<std::default_init_t>. Is that a compilation failure, undefined
behavior, certain member functions are undefined etc.?
2. std::default_init_t is a type that meets all the requirements for being
stored in a container. It's not good to add exceptions to rules if we don't
have to, vector<bool> being the canonical example of that.
3. LWG may have to spend time looking at the possible interactions between
std::default_init_t and *all* the libraries. LWG time is precious; I'd
rather see the time spent bringing more libraries into the standard.
If it is a nested type and instance, I believe that most (if not all) of
those problems go away.
Either way, beside construction, resize and insert member functions of the
various containers should also take those types as parameters.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
--0015174c0bfc0f4bf204ce5b4ae2
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On 12 November 2012 19:52, Nicol Bolas <span dir=3D"ltr"><<a href=3D"mai=
lto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></spa=
n> wrote:<br><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div><div class=3D"gmail_quote"><di=
v>Making value_init_t a nested type inside the container would take care of=
that case as well.</div>
</div>-- <br></div>=A0Nevin ":-)" Liber=A0 <mailto:<a>ne...@ev=
iloverlord.com</a><u></u>>=A0 <a href=3D"tel:%28847%29%20691-1404" value=
=3D"+18476911404" target=3D"_blank">(847) 691-1404</a><br></blockquote><div=
><br>Perhaps, but you also wouldn't be able to declare a single std::va=
lue_init_t, since it would change with each class template. And therefore, =
you couldn't define a global std::value_init value to use.</div>
</blockquote><div><br></div><div>Agreed. =A0There are, of course, advantage=
s to this, such as easier to use in generic code working with member initia=
lizers.</div><div><br></div><div>However, this is a small feature I would l=
ike to see in C++14 (actually, the one I really want to see is default_init=
_t, but the same argument applies), and I believe the impact of std::defaul=
t_init_t may end up pushing it to C++17 for the following reasons:</div>
<div><br></div><div>1. =A0It will take time to nail down what is meant by v=
ector<std::default_init_t>. =A0Is that a compilation failure, undefin=
ed behavior, certain member functions are undefined etc.?</div><div>2. =A0s=
td::default_init_t is a type that meets all the requirements for being stor=
ed in a container. It's not good to add exceptions to rules if we don&#=
39;t have to, vector<bool> being the canonical example of that.</div>
<div>3. =A0LWG may have to spend time looking at the possible interactions =
between std::default_init_t and *all* the libraries. =A0LWG time is preciou=
s; I'd rather see the time spent bringing more libraries into the stand=
ard.</div>
<div><br></div><div>If it is a nested type and instance, I believe that mos=
t (if not all) of those problems go away.</div><div><br></div><div>Either w=
ay, beside construction, resize and insert member functions of the various =
containers should also take those types as parameters.</div>
</div>-- <br>=A0Nevin ":-)" Liber=A0 <mailto:<a href=3D"mailto=
:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=
=A0 <a href=3D"tel:%28847%29%20691-1404" value=3D"+18476911404" target=3D"_=
blank">(847) 691-1404</a><br>
<p></p>
-- <br />
<br />
<br />
<br />
--0015174c0bfc0f4bf204ce5b4ae2--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 13 Nov 2012 06:26:18 -0800 (PST)
Raw View
------=_Part_1574_26841589.1352816778785
Content-Type: text/plain; charset=ISO-8859-1
The same way you did before. It's there to differentiate between list
initialization and non-list constructor initialization. `vector<int>{43}`
will still mean to create a vector with 1 integer that contains the integer
43. This will simply give us a way to specifically call the
value-construction initialization constructor via uniform initialization,
which is not currently possible. The initializer_list constructor for
`vector<int>` hides it.
It's no different than the use of `std::piecewise_construct` in one of
std::pair's constructors<http://en.cppreference.com/w/cpp/utility/pair/pair>.
It's there for overload resolution and nothing more.
On Monday, November 12, 2012 10:57:14 PM UTC-8, Arthur Tchaikovsky wrote:
>
> Nicol
>
> So with your proposal how would I go about initializing vector - the
> simplest/most common case, I want vector of ints and I want some values in
> it, would that be sufficient:
>
> vector<int> v{1,2,3};
>
> On Tuesday, 13 November 2012 01:52:36 UTC, Nicol Bolas wrote:
>>
>>
>>
>> On Monday, November 12, 2012 5:50:40 PM UTC-8, Nevin ":-)" Liber wrote:
>>>
>>> On 12 November 2012 18:50, Nicol Bolas <jmck...@gmail.com> wrote:
>>>
>>>> The constructor of `std::vector` that takes a single integer could be
>>>> extended to take an integer and a default parameter value of type
>>>> `std::value_init_t`. And `std::value_init` would be a value of that type.
>>>> The only way this initialization would be non-uniform is if you tried to
>>>> initialize a `vector<std::value_init_t>`s.
>>>>
>>>
>>> Making value_init_t a nested type inside the container would take care
>>> of that case as well.
>>> --
>>> Nevin ":-)" Liber <mailto:ne...@eviloverlord.com> (847) 691-1404
>>>
>>
>> Perhaps, but you also wouldn't be able to declare a single
>> std::value_init_t, since it would change with each class template. And
>> therefore, you couldn't define a global std::value_init value to use.
>>
>
--
------=_Part_1574_26841589.1352816778785
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
The same way you did before. It's there to differentiate between list initi=
alization and non-list constructor initialization. `vector<int>{43}` =
will still mean to create a vector with 1 integer that contains the integer=
43. This will simply give us a way to specifically call the value-construc=
tion initialization constructor via uniform initialization, which is not cu=
rrently possible. The initializer_list constructor for `vector<int>` =
hides it.<br><br>It's no different than the use of `std::piecewise_construc=
t` in <a href=3D"http://en.cppreference.com/w/cpp/utility/pair/pair">one of=
std::pair's constructors</a>. It's there for overload resolution and nothi=
ng more.<br><br>On Monday, November 12, 2012 10:57:14 PM UTC-8, Arthur Tcha=
ikovsky wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div>Nicol<br></=
div><div><br></div><div>So with your proposal how would I go about initiali=
zing vector - the simplest/most common case, I want vector of ints and I wa=
nt some values in it, would that be sufficient:</div><div><br></div><div>ve=
ctor<int> v{1,2,3};<br></div><div><br></div>On Tuesday, 13 November 2=
012 01:52:36 UTC, Nicol Bolas wrote:<blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><br><br>On Monday, November 12, 2012 5:50:40 PM UTC-8, Nevin ":-)" Liber =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex=
;border-left:1px #ccc solid;padding-left:1ex">On 12 November 2012 18:50, Ni=
col Bolas <span dir=3D"ltr"><<a>jmck...@gmail.com</a>></span> wrote:<=
br><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
The constructor of `std::vector` that takes a single integer could be exten=
ded to take an integer and a default parameter value of type `std::value_in=
it_t`. And `std::value_init` would be a value of that type. The only way th=
is initialization would be non-uniform is if you tried to initialize a `vec=
tor<std::value_init_t>`s.<br>
</blockquote><div><br></div><div>Making value_init_t a nested type inside t=
he container would take care of that case as well.</div></div>-- <br> =
Nevin ":-)" Liber <mailto:<a>ne...@eviloverlord.com</a><wbr>>&n=
bsp; (847) 691-1404<br></blockquote><div><br>Perhaps, but you also wouldn't=
be able to declare a single std::value_init_t, since it would change with =
each class template. And therefore, you couldn't define a global std::value=
_init value to use.<br></div></blockquote></blockquote>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_1574_26841589.1352816778785--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 13 Nov 2012 06:33:27 -0800 (PST)
Raw View
------=_Part_1_26255424.1352817207062
Content-Type: text/plain; charset=ISO-8859-1
On Monday, November 12, 2012 11:23:09 PM UTC-8, Nevin ":-)" Liber wrote:
>
> On 12 November 2012 19:52, Nicol Bolas <jmck...@gmail.com <javascript:>>wrote:
>
>> Making value_init_t a nested type inside the container would take care of
>>> that case as well.
>>> --
>>> Nevin ":-)" Liber <mailto:ne...@eviloverlord.com**> (847) 691-1404
>>>
>>
>> Perhaps, but you also wouldn't be able to declare a single
>> std::value_init_t, since it would change with each class template. And
>> therefore, you couldn't define a global std::value_init value to use.
>>
>
> Agreed. There are, of course, advantages to this, such as easier to use
> in generic code working with member initializers.
>
> However, this is a small feature I would like to see in C++14 (actually,
> the one I really want to see is default_init_t, but the same argument
> applies), and I believe the impact of std::default_init_t may end up
> pushing it to C++17 for the following reasons:
>
> 1. It will take time to nail down what is meant by
> vector<std::default_init_t>. Is that a compilation failure, undefined
> behavior, certain member functions are undefined etc.?
>
2. std::default_init_t is a type that meets all the requirements for being
> stored in a container. It's not good to add exceptions to rules if we don't
> have to, vector<bool> being the canonical example of that.
>
vector<bool> is a bad idea because it's a *bad idea*. It was a
poorly-designed class. Don't tar all specializations because it was used
badly in some instance.
Nobody will ever have any need for a vector<> of these types. There is no
legitimate use case for it where you couldn't simply use some other empty
class. As far as I'm concerned, simply disallowing it is no problem.
> 3. LWG may have to spend time looking at the possible interactions
> between std::default_init_t and *all* the libraries. LWG time is precious;
> I'd rather see the time spent bringing more libraries into the standard.
>
> If it is a nested type and instance, I believe that most (if not all) of
> those problems go away.
>
Except that it now becomes much less usable:
std::vector<int> vec1{43, std::vector<int>::default_init_t{}};
std::vector<int> vec2{43, std::default_init};
The `vec2` initializer is much easier to read.
> Either way, beside construction, resize and insert member functions of the
> various containers should also take those types as parameters.
> --
> Nevin ":-)" Liber <mailto:ne...@eviloverlord.com <javascript:>> (847)
> 691-1404
>
--
------=_Part_1_26255424.1352817207062
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, November 12, 2012 11:23:09 PM UTC-8, Nevin ":-)" Liber w=
rote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;">On 12 November 2012 19:52=
, Nicol Bolas <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blan=
k" gdf-obfuscated-mailto=3D"d5-ph8EvlOYJ">jmck...@gmail.com</a>></span> =
wrote:<br><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div><div class=3D"gmail_quote"><di=
v>Making value_init_t a nested type inside the container would take care of=
that case as well.</div>
</div>-- <br></div> Nevin ":-)" Liber <mailto:<a>ne...@evilov=
erlord.com</a><u></u><wbr>> <a value=3D"+18476911404">(847) 691-14=
04</a><br></blockquote><div><br>Perhaps, but you also wouldn't be able to d=
eclare a single std::value_init_t, since it would change with each class te=
mplate. And therefore, you couldn't define a global std::value_init value t=
o use.</div>
</blockquote><div><br></div><div>Agreed. There are, of course, advant=
ages to this, such as easier to use in generic code working with member ini=
tializers.</div><div><br></div><div>However, this is a small feature I woul=
d like to see in C++14 (actually, the one I really want to see is default_i=
nit_t, but the same argument applies), and I believe the impact of std::def=
ault_init_t may end up pushing it to C++17 for the following reasons:</div>
<div><br></div><div>1. It will take time to nail down what is meant b=
y vector<std::default_init_t>. Is that a compilation failure, u=
ndefined behavior, certain member functions are undefined etc.? <br></div><=
/div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div class=
=3D"gmail_quote"><div>2. std::default_init_t is a type that meets all=
the requirements for being stored in a container. It's not good to add exc=
eptions to rules if we don't have to, vector<bool> being the canonica=
l example of that.</div></div></blockquote><div><br>vector<bool> is a=
bad idea because it's a <i>bad idea</i>. It was a poorly-designed class. D=
on't tar all specializations because it was used badly in some instance.<br=
><br>Nobody will ever have any need for a vector<> of these types. Th=
ere is no legitimate use case for it where you couldn't simply use some oth=
er empty class. As far as I'm concerned, simply disallowing it is no proble=
m.<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 class=
=3D"gmail_quote">
<div>3. LWG may have to spend time looking at the possible interactio=
ns between std::default_init_t and *all* the libraries. LWG time is p=
recious; I'd rather see the time spent bringing more libraries into the sta=
ndard.</div>
<div><br></div><div>If it is a nested type and instance, I believe that mos=
t (if not all) of those problems go away.</div></div></blockquote><div><br>=
Except that it now becomes much less usable:<br><br><div class=3D"prettypri=
nt" 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 class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">std</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">vector</span><span style=3D"color: #080;" class=3D=
"styled-by-prettify"><int></span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> vec1</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">{</span><span style=3D"color: #066;" class=3D"styled-by-=
prettify">43</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">vector</span><span st=
yle=3D"color: #080;" class=3D"styled-by-prettify"><int></span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">default_init_t</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{}};</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>std</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify">vector</span><span style=3D"color: #080;" cla=
ss=3D"styled-by-prettify"><int></span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> vec2</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #066;" class=3D"style=
d-by-prettify">43</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">,</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">default_init</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">};</span></div=
></code></div><br>The `vec2` initializer is much easier to read.<br><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 class=3D"gmail_quote">=
<div><br></div><div>Either way, beside construction, resize and insert memb=
er functions of the various containers should also take those types as para=
meters.</div>
</div>-- <br> Nevin ":-)" Liber <mailto:<a href=3D"javascript=
:" target=3D"_blank" gdf-obfuscated-mailto=3D"d5-ph8EvlOYJ">ne...@eviloverl=
ord.com</a><wbr>> <a value=3D"+18476911404">(847) 691-1404</a><br>
</blockquote>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_1_26255424.1352817207062--
.
Author: Arthur Tchaikovsky <atch.cpp@gmail.com>
Date: Tue, 13 Nov 2012 06:57:09 -0800 (PST)
Raw View
------=_Part_67_6914487.1352818629193
Content-Type: text/plain; charset=ISO-8859-1
> std::vector<int> vec2{43, std::default_init};
Surely you won't have to have syntax where default needs to be specified. I
do understand other cases you mentioned like value_init, but for me if I
have to specify something extra which will get me default behavior is
simply bad design.
I do understand that:
std::vector<int> vec2{43};//<-- this is with default init and doesn't have
to be specified because is default
On Tuesday, 13 November 2012 14:33:27 UTC, Nicol Bolas wrote:
>
>
>
> On Monday, November 12, 2012 11:23:09 PM UTC-8, Nevin ":-)" Liber wrote:
>>
>> On 12 November 2012 19:52, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>> Making value_init_t a nested type inside the container would take care
>>>> of that case as well.
>>>> --
>>>> Nevin ":-)" Liber <mailto:ne...@eviloverlord.com**> (847) 691-1404
>>>>
>>>
>>> Perhaps, but you also wouldn't be able to declare a single
>>> std::value_init_t, since it would change with each class template. And
>>> therefore, you couldn't define a global std::value_init value to use.
>>>
>>
>> Agreed. There are, of course, advantages to this, such as easier to use
>> in generic code working with member initializers.
>>
>> However, this is a small feature I would like to see in C++14 (actually,
>> the one I really want to see is default_init_t, but the same argument
>> applies), and I believe the impact of std::default_init_t may end up
>> pushing it to C++17 for the following reasons:
>>
>> 1. It will take time to nail down what is meant by
>> vector<std::default_init_t>. Is that a compilation failure, undefined
>> behavior, certain member functions are undefined etc.?
>>
> 2. std::default_init_t is a type that meets all the requirements for
>> being stored in a container. It's not good to add exceptions to rules if we
>> don't have to, vector<bool> being the canonical example of that.
>>
>
> vector<bool> is a bad idea because it's a *bad idea*. It was a
> poorly-designed class. Don't tar all specializations because it was used
> badly in some instance.
>
> Nobody will ever have any need for a vector<> of these types. There is no
> legitimate use case for it where you couldn't simply use some other empty
> class. As far as I'm concerned, simply disallowing it is no problem.
>
>
>> 3. LWG may have to spend time looking at the possible interactions
>> between std::default_init_t and *all* the libraries. LWG time is precious;
>> I'd rather see the time spent bringing more libraries into the standard.
>>
>> If it is a nested type and instance, I believe that most (if not all) of
>> those problems go away.
>>
>
> Except that it now becomes much less usable:
>
> std::vector<int> vec1{43, std::vector<int>::default_init_t{}};
> std::vector<int> vec2{43, std::default_init};
>
> The `vec2` initializer is much easier to read.
>
>
>> Either way, beside construction, resize and insert member functions of
>> the various containers should also take those types as parameters.
>> --
>> Nevin ":-)" Liber <mailto:ne...@eviloverlord.com> (847) 691-1404
>>
>
--
------=_Part_67_6914487.1352818629193
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<br><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-s=
tyle: solid; padding-left: 1ex;"><span style=3D"font-family: monospace; bac=
kground-color: rgb(250, 250, 250); color: rgb(0, 0, 0);">std</span><span st=
yle=3D"font-family: monospace; background-color: rgb(250, 250, 250); color:=
rgb(102, 102, 0);">::</span><span style=3D"font-family: monospace; backgro=
und-color: rgb(250, 250, 250); color: rgb(0, 0, 0);">vector</span><span sty=
le=3D"font-family: monospace; background-color: rgb(250, 250, 250); color: =
rgb(0, 136, 0);"><int></span><span style=3D"font-family: monospace; b=
ackground-color: rgb(250, 250, 250); color: rgb(0, 0, 0);"> vec2</span=
><span style=3D"font-family: monospace; background-color: rgb(250, 250, 250=
); color: rgb(102, 102, 0);">{</span><span style=3D"font-family: monospace;=
background-color: rgb(250, 250, 250); color: rgb(0, 102, 102);">43</span><=
span style=3D"font-family: monospace; background-color: rgb(250, 250, 250);=
color: rgb(102, 102, 0);">,</span><span style=3D"font-family: monospace; b=
ackground-color: rgb(250, 250, 250); color: rgb(0, 0, 0);"> std</span>=
<span style=3D"font-family: monospace; background-color: rgb(250, 250, 250)=
; color: rgb(102, 102, 0);">::</span><span style=3D"font-family: monospace;=
background-color: rgb(250, 250, 250); color: rgb(0, 0, 0);">default_init</=
span><span style=3D"font-family: monospace; background-color: rgb(250, 250,=
250); color: rgb(102, 102, 0);">};</span></blockquote><div><br></div><div>=
Surely you won't have to have syntax where default needs to be specified. I=
do understand other cases you mentioned like value_init, but for me if I h=
ave to specify something extra which will get me default behavior is simply=
bad design.</div><div><br></div><div>I do understand that:</div><div> =
;<span style=3D"font-family: monospace; background-color: rgb(250, 250, 250=
); color: rgb(0, 0, 0);">std</span><span style=3D"font-family: monospace; b=
ackground-color: rgb(250, 250, 250); color: rgb(102, 102, 0);">::</span><sp=
an style=3D"font-family: monospace; background-color: rgb(250, 250, 250); c=
olor: rgb(0, 0, 0);">vector</span><span style=3D"font-family: monospace; ba=
ckground-color: rgb(250, 250, 250); color: rgb(0, 136, 0);"><int></sp=
an><span style=3D"font-family: monospace; background-color: rgb(250, 250, 2=
50); color: rgb(0, 0, 0);"> vec2</span><span style=3D"font-family: mon=
ospace; background-color: rgb(250, 250, 250); color: rgb(102, 102, 0);">{</=
span><span style=3D"font-family: monospace; background-color: rgb(250, 250,=
250);"><font color=3D"#006666">43</font></span><span style=3D"font-family:=
monospace; background-color: rgb(250, 250, 250); color: rgb(102, 102, 0);"=
>};//<-- this is with default init and doesn't have to be specified beca=
use is default</span></div><div><span style=3D"font-family: monospace; back=
ground-color: rgb(250, 250, 250); color: rgb(102, 102, 0);"><br></span></di=
v>On Tuesday, 13 November 2012 14:33:27 UTC, Nicol Bolas wrote:<blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><br><br>On Monday, November 12, 2012 11:2=
3:09 PM UTC-8, Nevin ":-)" Liber wrote:<blockquote class=3D"gmail_quote" st=
yle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1=
ex">On 12 November 2012 19:52, Nicol Bolas <span dir=3D"ltr"><<a>jmck...=
@gmail.com</a>></span> wrote:<br><div class=3D"gmail_quote"><blockquote =
class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid=
;padding-left:1ex">
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div><div class=3D"gmail_quote"><di=
v>Making value_init_t a nested type inside the container would take care of=
that case as well.</div>
</div>-- <br></div> Nevin ":-)" Liber <mailto:<a>ne...@evilov=
erlord.com</a><u></u><wbr>> <a value=3D"+18476911404">(847) 691-14=
04</a><br></blockquote><div><br>Perhaps, but you also wouldn't be able to d=
eclare a single std::value_init_t, since it would change with each class te=
mplate. And therefore, you couldn't define a global std::value_init value t=
o use.</div>
</blockquote><div><br></div><div>Agreed. There are, of course, advant=
ages to this, such as easier to use in generic code working with member ini=
tializers.</div><div><br></div><div>However, this is a small feature I woul=
d like to see in C++14 (actually, the one I really want to see is default_i=
nit_t, but the same argument applies), and I believe the impact of std::def=
ault_init_t may end up pushing it to C++17 for the following reasons:</div>
<div><br></div><div>1. It will take time to nail down what is meant b=
y vector<std::default_init_t>. Is that a compilation failure, u=
ndefined behavior, certain member functions are undefined etc.? <br></div><=
/div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin:0;margi=
n-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div class=3D"gma=
il_quote"><div>2. std::default_init_t is a type that meets all the re=
quirements for being stored in a container. It's not good to add exceptions=
to rules if we don't have to, vector<bool> being the canonical examp=
le of that.</div></div></blockquote><div><br>vector<bool> is a bad id=
ea because it's a <i>bad idea</i>. It was a poorly-designed class. Don't ta=
r all specializations because it was used badly in some instance.<br><br>No=
body will ever have any need for a vector<> of these types. There is =
no legitimate use case for it where you couldn't simply use some other empt=
y class. As far as I'm concerned, simply disallowing it is no problem.<br>&=
nbsp;</div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:=
0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div class=3D"gmail_quot=
e">
<div>3. LWG may have to spend time looking at the possible interactio=
ns between std::default_init_t and *all* the libraries. LWG time is p=
recious; I'd rather see the time spent bringing more libraries into the sta=
ndard.</div>
<div><br></div><div>If it is a nested type and instance, I believe that mos=
t (if not all) of those problems go away.</div></div></blockquote><div><br>=
Except that it now becomes much less usable:<br><br><div style=3D"backgroun=
d-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;b=
order-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">v=
ector</span><span style=3D"color:#080"><int></span><span style=3D"col=
or:#000"> vec1</span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#066">43</span><span style=3D"color:#660">,</span><span style=3D"color:#0=
00"> std</span><span style=3D"color:#660">::</span><span style=3D"color:#00=
0">vector</span><span style=3D"color:#080"><int></span><span style=3D=
"color:#660">::</span><span style=3D"color:#000">default_<wbr>init_t</span>=
<span style=3D"color:#660">{}};</span><span style=3D"color:#000"><br>std</s=
pan><span style=3D"color:#660">::</span><span style=3D"color:#000">vector</=
span><span style=3D"color:#080"><int></span><span style=3D"color:#000=
"> vec2</span><span style=3D"color:#660">{</span><span style=3D"color:#066"=
>43</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> st=
d</span><span style=3D"color:#660">::</span><span style=3D"color:#000">defa=
ult_init</span><span style=3D"color:#660">};</span></div></code></div><br>T=
he `vec2` initializer is much easier to read.<br><br></div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div class=3D"gmail_quote"><div><br></div><div>Eith=
er way, beside construction, resize and insert member functions of the vari=
ous containers should also take those types as parameters.</div>
</div>-- <br> Nevin ":-)" Liber <mailto:<a>ne...@eviloverlord=
..com</a><wbr>> <a value=3D"+18476911404">(847) 691-1404</a><br>
</blockquote></blockquote>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_67_6914487.1352818629193--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Tue, 13 Nov 2012 17:01:53 +0200
Raw View
On 13 November 2012 16:57, Arthur Tchaikovsky <atch.cpp@gmail.com> wrote:
>> std::vector<int> vec2{43, std::default_init};
> Surely you won't have to have syntax where default needs to be specified. I
> do understand other cases you mentioned like value_init, but for me if I
> have to specify something extra which will get me default behavior is simply
> bad design.
> I do understand that:
> std::vector<int> vec2{43};//<-- this is with default init and doesn't have
> to be specified because is default
Well, the first,
std::vector<int> vec2{43, std::default_init};
creates a vector of 43 default-initialized ints. The latter,
std::vector<int> vec2{43};
creates a vector of one int with the value 43. The first is spelled as
it is in order
to avoid this ambiguity, so the init_kind argument acts as an overload
resolution
selector, allowing an invocation of a constructor such as
vector(size_t howmany, init_kind howtoinit);
--
.
Author: Arthur Tchaikovsky <atch.cpp@gmail.com>
Date: Tue, 13 Nov 2012 08:55:12 -0800 (PST)
Raw View
------=_Part_254_17878722.1352825712079
Content-Type: text/plain; charset=ISO-8859-1
>
> Well, the first,
>
std::vector<int> vec2{43, std::default_init};
creates a vector of 43 default-initialized ints. The latter,
std::vector<int> vec2{43};
creates a vector of one int with the value 43.
Then I have to say that this is simply bad idea. As for confusion, more
things to learn etc. This is simply getting unwieldy. If anything something
like method of initialization should be done in a template param list, for
example:
std::vector<int, std::default_init> vec2(43);
What Nicol proposes is confusing (I'm not saying that mine isn't). What is
initialized by default? The vector? The objects stored in this vector? I'm
not saying that having some mechanism as proposed by Nicol is bad, on the
contrary, but I think he didn't give enough thought to his idea and is
simply not even half baked. Not getting back at him as I more concerned
with the future state of c++ than with his unpleasant remarks directed at
me.
On Tuesday, 13 November 2012 15:01:54 UTC, Ville Voutilainen wrote:
>
> On 13 November 2012 16:57, Arthur Tchaikovsky <atch...@gmail.com<javascript:>>
> wrote:
> >> std::vector<int> vec2{43, std::default_init};
> > Surely you won't have to have syntax where default needs to be
> specified. I
> > do understand other cases you mentioned like value_init, but for me if I
> > have to specify something extra which will get me default behavior is
> simply
> > bad design.
> > I do understand that:
> > std::vector<int> vec2{43};//<-- this is with default init and doesn't
> have
> > to be specified because is default
>
> Well, the first,
>
> std::vector<int> vec2{43, std::default_init};
>
> creates a vector of 43 default-initialized ints. The latter,
>
> std::vector<int> vec2{43};
>
> creates a vector of one int with the value 43. The first is spelled as
> it is in order
> to avoid this ambiguity, so the init_kind argument acts as an overload
> resolution
> selector, allowing an invocation of a constructor such as
>
> vector(size_t howmany, init_kind howtoinit);
>
--
------=_Part_254_17878722.1352825712079
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;">
Well, the first,
<br></blockquote>
<blockquote>std::vector<int> vec2{43, std::default_init}; <br></=
blockquote>
<blockquote>creates a vector of 43 default-initialized ints. The latter,&nb=
sp;<br></blockquote>
<blockquote>std::vector<int> vec2{43}; <br></blockquote>
<blockquote>creates a vector of one int with the value 43. <br></block=
quote><div><br></div><div>Then I have to say that this is simply bad idea. =
As for confusion, more things to learn etc. This is simply getting unwieldy=
.. If anything something like method of initialization should be done in a t=
emplate param list, for example:</div><div><br></div><div> std::vector=
<int, std::default_init> vec2(43); </div><div><br></div><div>Wh=
at Nicol proposes is confusing (I'm not saying that mine isn't). What is in=
itialized by default? The vector? The objects stored in this vector? I'm no=
t saying that having some mechanism as proposed by Nicol is bad, on the con=
trary, but I think he didn't give enough thought to his idea and is simply =
not even half baked. Not getting back at him as I more concerned with the f=
uture state of c++ than with his unpleasant remarks directed at me.</div><d=
iv><br></div>On Tuesday, 13 November 2012 15:01:54 UTC, Ville Voutilainen =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 13 November 2012 16:5=
7, Arthur Tchaikovsky <<a href=3D"javascript:" target=3D"_blank" gdf-obf=
uscated-mailto=3D"wiAujjqPVxkJ">atch...@gmail.com</a>> wrote:
<br>>> std::vector<int> vec2{43, std::default_init};
<br>> Surely you won't have to have syntax where default needs to be spe=
cified. I
<br>> do understand other cases you mentioned like value_init, but for m=
e if I
<br>> have to specify something extra which will get me default behavior=
is simply
<br>> bad design.
<br>> I do understand that:
<br>> std::vector<int> vec2{43};//<-- this is with defaul=
t init and doesn't have
<br>> to be specified because is default
<br>
<br>Well, the first,
<br>
<br>std::vector<int> vec2{43, std::default_init};
<br>
<br>creates a vector of 43 default-initialized ints. The latter,
<br>
<br>std::vector<int> vec2{43};
<br>
<br>creates a vector of one int with the value 43. The first is spelled as
<br>it is in order
<br>to avoid this ambiguity, so the init_kind argument acts as an overload
<br>resolution
<br>selector, allowing an invocation of a constructor such as
<br>
<br>vector(size_t howmany, init_kind howtoinit);
<br></blockquote>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_254_17878722.1352825712079--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 13 Nov 2012 09:27:11 -0800 (PST)
Raw View
------=_Part_1382_17692383.1352827631450
Content-Type: text/plain; charset=ISO-8859-1
On Tuesday, November 13, 2012 8:55:12 AM UTC-8, Arthur Tchaikovsky wrote:
>
> Well, the first,
>>
> std::vector<int> vec2{43, std::default_init};
>
> creates a vector of 43 default-initialized ints. The latter,
>
> std::vector<int> vec2{43};
>
> creates a vector of one int with the value 43.
>
>
> Then I have to say that this is simply bad idea. As for confusion, more
> things to learn etc. This is simply getting unwieldy. If anything something
> like method of initialization should be done in a template param list, for
> example:
>
> std::vector<int, std::default_init> vec2(43);
>
Besides the fact that this would be a breaking change (and therefore a
non-starter), that's not what I'm talking about. I don't even know how we
got onto `std::default_init` to begin with. This post was about `std::*
value_init*`; default_init was another thread with a different purpose.
The purpose of this feature is to allow uniform initialization to actually
be *uniform*. These:
std::vector<int> vec1(43); //Create a vector with 43 zeros.
std::vector<int> vec2{43}; //Create a vector containing one entry.
These are not the same. In most cases, using () and {} will give the same
results. But not here. And this is a trap people fall into *all the time.*
That's why we need a uniform mechanism for value initialization (ie: create
a vector with 43 zeros) that won't be confused for list initialization:
std::vector<int> vec1(43, std::value_init); //Create a vector with 43 zeros.
std::vector<int> vec2{43, std::value_init}; //Create a vector with 43 zeros.
This is uniform; it works the same way in both places. And that's good.
For backwards compatibility, we won't *require* std::value_init for that
constructor (and similar functions). But we will allow it.
What Nicol proposes is confusing (I'm not saying that mine isn't). What is
> initialized by default? The vector? The objects stored in this vector? I'm
> not saying that having some mechanism as proposed by Nicol is bad, on the
> contrary, but I think he didn't give enough thought to his idea and is
> simply not even half baked. Not getting back at him as I more concerned
> with the future state of c++ than with his unpleasant remarks directed at
> me.
>
This is a conversation best had in the proper thread<https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/4BHDIXgCcL8>.
These features are orthogonal (though obviously related). However, the name
of it, whether it's std::default_init, std::default_value, std::whatever,
is a bikeshed issue that shouldn't hold up the feature itself.
>
> On Tuesday, 13 November 2012 15:01:54 UTC, Ville Voutilainen wrote:
>>
>> On 13 November 2012 16:57, Arthur Tchaikovsky <atch...@gmail.com> wrote:
>> >> std::vector<int> vec2{43, std::default_init};
>> > Surely you won't have to have syntax where default needs to be
>> specified. I
>> > do understand other cases you mentioned like value_init, but for me if
>> I
>> > have to specify something extra which will get me default behavior is
>> simply
>> > bad design.
>> > I do understand that:
>> > std::vector<int> vec2{43};//<-- this is with default init and doesn't
>> have
>> > to be specified because is default
>>
>> Well, the first,
>>
>> std::vector<int> vec2{43, std::default_init};
>>
>> creates a vector of 43 default-initialized ints. The latter,
>>
>> std::vector<int> vec2{43};
>>
>> creates a vector of one int with the value 43. The first is spelled as
>> it is in order
>> to avoid this ambiguity, so the init_kind argument acts as an overload
>> resolution
>> selector, allowing an invocation of a constructor such as
>>
>> vector(size_t howmany, init_kind howtoinit);
>>
>
--
------=_Part_1382_17692383.1352827631450
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<br><br>On Tuesday, November 13, 2012 8:55:12 AM UTC-8, Arthur Tchaikovsky =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex">
Well, the first,
<br></blockquote>
<blockquote>std::vector<int> vec2{43, std::default_init}; <br></=
blockquote>
<blockquote>creates a vector of 43 default-initialized ints. The latter,&nb=
sp;<br></blockquote>
<blockquote>std::vector<int> vec2{43}; <br></blockquote>
<blockquote>creates a vector of one int with the value 43. <br></block=
quote><div><br></div><div>Then I have to say that this is simply bad idea. =
As for confusion, more things to learn etc. This is simply getting unwieldy=
.. If anything something like method of initialization should be done in a t=
emplate param list, for example:</div><div><br></div><div> std::vector=
<int, std::default_init> vec2(43);<br></div></blockquote><div><br>Bes=
ides the fact that this would be a breaking change (and therefore a non-sta=
rter), that's not what I'm talking about. I don't even know how we got onto=
`std::default_init` to begin with. This post was about `std::<i>value_init=
</i>`; default_init was another thread with a different purpose.<br><br>The=
purpose of this feature is to allow uniform initialization to actually be =
<i>uniform</i>. These:<br><br>std::vector<int> vec1(43); //Create a v=
ector with 43 zeros.<br>std::vector<int> vec2{43}; //Create a vector =
containing one entry.<br><br>These are not the same. In most cases, using (=
) and {} will give the same results. But not here. And this is a trap peopl=
e fall into <i>all the time.</i><br><br>That's why we need a uniform mechan=
ism for value initialization (ie: create a vector with 43 zeros) that won't=
be confused for list initialization:<br><br>std::vector<int> vec1(43=
, std::value_init); //Create a vector with 43 zeros.<br>std::vector<int&=
gt; vec2{43, std::value_init}; //Create a vector with 43 zeros.<br><br>This=
is uniform; it works the same way in both places. And that's good.<br><br>=
For backwards compatibility, we won't <i>require</i> std::value_init for th=
at constructor (and similar functions). But we will allow it.<br><br></div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div></div><div></div><div>Wha=
t Nicol proposes is confusing (I'm not saying that mine isn't). What is ini=
tialized by default? The vector? The objects stored in this vector? I'm not=
saying that having some mechanism as proposed by Nicol is bad, on the cont=
rary, but I think he didn't give enough thought to his idea and is simply n=
ot even half baked. Not getting back at him as I more concerned with the fu=
ture state of c++ than with his unpleasant remarks directed at me.</div></b=
lockquote><div><br>This is a conversation best had <a href=3D"https://group=
s.google.com/a/isocpp.org/forum/#!topic/std-proposals/4BHDIXgCcL8">in the p=
roper thread</a>. These features are orthogonal (though obviously related).=
However, the name of it, whether it's std::default_init, std::default_valu=
e, std::whatever, is a bikeshed issue that shouldn't hold up the feature it=
self.<br> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div><br>=
</div>On Tuesday, 13 November 2012 15:01:54 UTC, Ville Voutilainen wrote:<=
blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border=
-left:1px #ccc solid;padding-left:1ex">On 13 November 2012 16:57, Arthur Tc=
haikovsky <<a>atch...@gmail.com</a>> wrote:
<br>>> std::vector<int> vec2{43, std::default_init};
<br>> Surely you won't have to have syntax where default needs to be spe=
cified. I
<br>> do understand other cases you mentioned like value_init, but for m=
e if I
<br>> have to specify something extra which will get me default behavior=
is simply
<br>> bad design.
<br>> I do understand that:
<br>> std::vector<int> vec2{43};//<-- this is with defaul=
t init and doesn't have
<br>> to be specified because is default
<br>
<br>Well, the first,
<br>
<br>std::vector<int> vec2{43, std::default_init};
<br>
<br>creates a vector of 43 default-initialized ints. The latter,
<br>
<br>std::vector<int> vec2{43};
<br>
<br>creates a vector of one int with the value 43. The first is spelled as
<br>it is in order
<br>to avoid this ambiguity, so the init_kind argument acts as an overload
<br>resolution
<br>selector, allowing an invocation of a constructor such as
<br>
<br>vector(size_t howmany, init_kind howtoinit);
<br></blockquote></blockquote>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_1382_17692383.1352827631450--
.
Author: Arthur Tchaikovsky <atch.cpp@gmail.com>
Date: Wed, 14 Nov 2012 03:16:35 -0800 (PST)
Raw View
------=_Part_680_28895507.1352891795836
Content-Type: text/plain; charset=ISO-8859-1
Hi Nicol
After giving it some thought I do see value in your proposal. That said, I
still believe that default case should be as minimal as possible, and only
unusual behavior should be indicated.
Looking forward to hear from you.
On Tuesday, 13 November 2012 17:27:11 UTC, Nicol Bolas wrote:
>
>
>
> On Tuesday, November 13, 2012 8:55:12 AM UTC-8, Arthur Tchaikovsky wrote:
>>
>> Well, the first,
>>>
>> std::vector<int> vec2{43, std::default_init};
>>
>> creates a vector of 43 default-initialized ints. The latter,
>>
>> std::vector<int> vec2{43};
>>
>> creates a vector of one int with the value 43.
>>
>>
>> Then I have to say that this is simply bad idea. As for confusion, more
>> things to learn etc. This is simply getting unwieldy. If anything something
>> like method of initialization should be done in a template param list, for
>> example:
>>
>> std::vector<int, std::default_init> vec2(43);
>>
>
> Besides the fact that this would be a breaking change (and therefore a
> non-starter), that's not what I'm talking about. I don't even know how we
> got onto `std::default_init` to begin with. This post was about `std::*
> value_init*`; default_init was another thread with a different purpose.
>
> The purpose of this feature is to allow uniform initialization to actually
> be *uniform*. These:
>
> std::vector<int> vec1(43); //Create a vector with 43 zeros.
> std::vector<int> vec2{43}; //Create a vector containing one entry.
>
> These are not the same. In most cases, using () and {} will give the same
> results. But not here. And this is a trap people fall into *all the time.*
>
> That's why we need a uniform mechanism for value initialization (ie:
> create a vector with 43 zeros) that won't be confused for list
> initialization:
>
> std::vector<int> vec1(43, std::value_init); //Create a vector with 43
> zeros.
> std::vector<int> vec2{43, std::value_init}; //Create a vector with 43
> zeros.
>
> This is uniform; it works the same way in both places. And that's good.
>
> For backwards compatibility, we won't *require* std::value_init for that
> constructor (and similar functions). But we will allow it.
>
> What Nicol proposes is confusing (I'm not saying that mine isn't). What is
>> initialized by default? The vector? The objects stored in this vector? I'm
>> not saying that having some mechanism as proposed by Nicol is bad, on the
>> contrary, but I think he didn't give enough thought to his idea and is
>> simply not even half baked. Not getting back at him as I more concerned
>> with the future state of c++ than with his unpleasant remarks directed at
>> me.
>>
>
> This is a conversation best had in the proper thread<https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/4BHDIXgCcL8>.
> These features are orthogonal (though obviously related). However, the name
> of it, whether it's std::default_init, std::default_value, std::whatever,
> is a bikeshed issue that shouldn't hold up the feature itself.
>
>
>>
>> On Tuesday, 13 November 2012 15:01:54 UTC, Ville Voutilainen wrote:
>>>
>>> On 13 November 2012 16:57, Arthur Tchaikovsky <atch...@gmail.com>
>>> wrote:
>>> >> std::vector<int> vec2{43, std::default_init};
>>> > Surely you won't have to have syntax where default needs to be
>>> specified. I
>>> > do understand other cases you mentioned like value_init, but for me if
>>> I
>>> > have to specify something extra which will get me default behavior is
>>> simply
>>> > bad design.
>>> > I do understand that:
>>> > std::vector<int> vec2{43};//<-- this is with default init and doesn't
>>> have
>>> > to be specified because is default
>>>
>>> Well, the first,
>>>
>>> std::vector<int> vec2{43, std::default_init};
>>>
>>> creates a vector of 43 default-initialized ints. The latter,
>>>
>>> std::vector<int> vec2{43};
>>>
>>> creates a vector of one int with the value 43. The first is spelled as
>>> it is in order
>>> to avoid this ambiguity, so the init_kind argument acts as an overload
>>> resolution
>>> selector, allowing an invocation of a constructor such as
>>>
>>> vector(size_t howmany, init_kind howtoinit);
>>>
>>
--
------=_Part_680_28895507.1352891795836
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div>Hi Nicol<br></div><div><br></div><div>After giving it some thought I d=
o see value in your proposal. That said, I still believe that default case =
should be as minimal as possible, and only unusual behavior should be indic=
ated.</div><div><br></div><div>Looking forward to hear from you.</div><br>O=
n Tuesday, 13 November 2012 17:27:11 UTC, Nicol Bolas wrote:<blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px =
#ccc solid;padding-left: 1ex;"><br><br>On Tuesday, November 13, 2012 8:55:1=
2 AM UTC-8, Arthur Tchaikovsky wrote:<blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bor=
der-left:1px #ccc solid;padding-left:1ex">
Well, the first,
<br></blockquote>
<blockquote>std::vector<int> vec2{43, std::default_init}; <br></=
blockquote>
<blockquote>creates a vector of 43 default-initialized ints. The latter,&nb=
sp;<br></blockquote>
<blockquote>std::vector<int> vec2{43}; <br></blockquote>
<blockquote>creates a vector of one int with the value 43. <br></block=
quote><div><br></div><div>Then I have to say that this is simply bad idea. =
As for confusion, more things to learn etc. This is simply getting unwieldy=
.. If anything something like method of initialization should be done in a t=
emplate param list, for example:</div><div><br></div><div> std::vector=
<int, std::default_init> vec2(43);<br></div></blockquote><div><br>Bes=
ides the fact that this would be a breaking change (and therefore a non-sta=
rter), that's not what I'm talking about. I don't even know how we got onto=
`std::default_init` to begin with. This post was about `std::<i>value_init=
</i>`; default_init was another thread with a different purpose.<br><br>The=
purpose of this feature is to allow uniform initialization to actually be =
<i>uniform</i>. These:<br><br>std::vector<int> vec1(43); //Create a v=
ector with 43 zeros.<br>std::vector<int> vec2{43}; //Create a vector =
containing one entry.<br><br>These are not the same. In most cases, using (=
) and {} will give the same results. But not here. And this is a trap peopl=
e fall into <i>all the time.</i><br><br>That's why we need a uniform mechan=
ism for value initialization (ie: create a vector with 43 zeros) that won't=
be confused for list initialization:<br><br>std::vector<int> vec1(43=
, std::value_init); //Create a vector with 43 zeros.<br>std::vector<int&=
gt; vec2{43, std::value_init}; //Create a vector with 43 zeros.<br><br>This=
is uniform; it works the same way in both places. And that's good.<br><br>=
For backwards compatibility, we won't <i>require</i> std::value_init for th=
at constructor (and similar functions). But we will allow it.<br><br></div>=
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div>What Nicol proposes is confusi=
ng (I'm not saying that mine isn't). What is initialized by default? The ve=
ctor? The objects stored in this vector? I'm not saying that having some me=
chanism as proposed by Nicol is bad, on the contrary, but I think he didn't=
give enough thought to his idea and is simply not even half baked. Not get=
ting back at him as I more concerned with the future state of c++ than with=
his unpleasant remarks directed at me.</div></blockquote><div><br>This is =
a conversation best had <a href=3D"https://groups.google.com/a/isocpp.org/f=
orum/#!topic/std-proposals/4BHDIXgCcL8" target=3D"_blank">in the proper thr=
ead</a>. These features are orthogonal (though obviously related). However,=
the name of it, whether it's std::default_init, std::default_value, std::w=
hatever, is a bikeshed issue that shouldn't hold up the feature itself.<br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left=
:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div><br></div>On Tuesd=
ay, 13 November 2012 15:01:54 UTC, Ville Voutilainen wrote:<blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc=
solid;padding-left:1ex">On 13 November 2012 16:57, Arthur Tchaikovsky <=
<a>atch...@gmail.com</a>> wrote:
<br>>> std::vector<int> vec2{43, std::default_init};
<br>> Surely you won't have to have syntax where default needs to be spe=
cified. I
<br>> do understand other cases you mentioned like value_init, but for m=
e if I
<br>> have to specify something extra which will get me default behavior=
is simply
<br>> bad design.
<br>> I do understand that:
<br>> std::vector<int> vec2{43};//<-- this is with defaul=
t init and doesn't have
<br>> to be specified because is default
<br>
<br>Well, the first,
<br>
<br>std::vector<int> vec2{43, std::default_init};
<br>
<br>creates a vector of 43 default-initialized ints. The latter,
<br>
<br>std::vector<int> vec2{43};
<br>
<br>creates a vector of one int with the value 43. The first is spelled as
<br>it is in order
<br>to avoid this ambiguity, so the init_kind argument acts as an overload
<br>resolution
<br>selector, allowing an invocation of a constructor such as
<br>
<br>vector(size_t howmany, init_kind howtoinit);
<br></blockquote></blockquote></blockquote>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_680_28895507.1352891795836--
.
Author: malteskarupke@gmail.com
Date: Sat, 29 Dec 2012 09:36:46 -0800 (PST)
Raw View
------=_Part_1475_6085227.1356802606872
Content-Type: text/plain; charset=ISO-8859-1
I would like to see this behavior:
std::vector<int> a{10}; // does not use initializer list constructor.
creates a vector with ten elements
std::vector<int> b{10, 20, 30}; // calls initializer list constructor
std::vector<int> c{{10}}; // calls initializer list constructor, creates
vector with the element 10
std::vector<int> d{std::move(b)}; // does not use initializer list
constructor, calls move constructor
std::vector<std::function<void ()>> e{}; // default constructor
std::vector<std::function<void ()>> f{std::move(e)}; // expect same
behavior as d
Currently the last line does not compile because it tries to use the
initializer_list constructor.
What I want is that first the compiler tries all non-initializer_list
constructors, and that it only uses the initializer_list one if none of
those work.
Currently you can't use uniform initialization in generic code, because it
can break where initialization with parenthesis wouldn't break if someone
uses your code with an object with an initializer list constructor. Which
is a shame. Uniform initialization would be great for generic code.
Cheers,
Malte
Am Mittwoch, 14. November 2012 12:16:36 UTC+1 schrieb Arthur Tchaikovsky:
>
> Hi Nicol
>
> After giving it some thought I do see value in your proposal. That said, I
> still believe that default case should be as minimal as possible, and only
> unusual behavior should be indicated.
>
> Looking forward to hear from you.
>
> On Tuesday, 13 November 2012 17:27:11 UTC, Nicol Bolas wrote:
>>
>>
>>
>> On Tuesday, November 13, 2012 8:55:12 AM UTC-8, Arthur Tchaikovsky wrote:
>>>
>>> Well, the first,
>>>>
>>> std::vector<int> vec2{43, std::default_init};
>>>
>>> creates a vector of 43 default-initialized ints. The latter,
>>>
>>> std::vector<int> vec2{43};
>>>
>>> creates a vector of one int with the value 43.
>>>
>>>
>>> Then I have to say that this is simply bad idea. As for confusion, more
>>> things to learn etc. This is simply getting unwieldy. If anything something
>>> like method of initialization should be done in a template param list, for
>>> example:
>>>
>>> std::vector<int, std::default_init> vec2(43);
>>>
>>
>> Besides the fact that this would be a breaking change (and therefore a
>> non-starter), that's not what I'm talking about. I don't even know how we
>> got onto `std::default_init` to begin with. This post was about `std::*
>> value_init*`; default_init was another thread with a different purpose.
>>
>> The purpose of this feature is to allow uniform initialization to
>> actually be *uniform*. These:
>>
>> std::vector<int> vec1(43); //Create a vector with 43 zeros.
>> std::vector<int> vec2{43}; //Create a vector containing one entry.
>>
>> These are not the same. In most cases, using () and {} will give the same
>> results. But not here. And this is a trap people fall into *all the time.
>> *
>>
>> That's why we need a uniform mechanism for value initialization (ie:
>> create a vector with 43 zeros) that won't be confused for list
>> initialization:
>>
>> std::vector<int> vec1(43, std::value_init); //Create a vector with 43
>> zeros.
>> std::vector<int> vec2{43, std::value_init}; //Create a vector with 43
>> zeros.
>>
>> This is uniform; it works the same way in both places. And that's good.
>>
>> For backwards compatibility, we won't *require* std::value_init for that
>> constructor (and similar functions). But we will allow it.
>>
>> What Nicol proposes is confusing (I'm not saying that mine isn't). What
>>> is initialized by default? The vector? The objects stored in this vector?
>>> I'm not saying that having some mechanism as proposed by Nicol is bad, on
>>> the contrary, but I think he didn't give enough thought to his idea and is
>>> simply not even half baked. Not getting back at him as I more concerned
>>> with the future state of c++ than with his unpleasant remarks directed at
>>> me.
>>>
>>
>> This is a conversation best had in the proper thread<https://groups.google.com/a/isocpp.org/forum/#%21topic/std-proposals/4BHDIXgCcL8>.
>> These features are orthogonal (though obviously related). However, the name
>> of it, whether it's std::default_init, std::default_value, std::whatever,
>> is a bikeshed issue that shouldn't hold up the feature itself.
>>
>>
>>>
>>> On Tuesday, 13 November 2012 15:01:54 UTC, Ville Voutilainen wrote:
>>>>
>>>> On 13 November 2012 16:57, Arthur Tchaikovsky <atch...@gmail.com>
>>>> wrote:
>>>> >> std::vector<int> vec2{43, std::default_init};
>>>> > Surely you won't have to have syntax where default needs to be
>>>> specified. I
>>>> > do understand other cases you mentioned like value_init, but for me
>>>> if I
>>>> > have to specify something extra which will get me default behavior is
>>>> simply
>>>> > bad design.
>>>> > I do understand that:
>>>> > std::vector<int> vec2{43};//<-- this is with default init and
>>>> doesn't have
>>>> > to be specified because is default
>>>>
>>>> Well, the first,
>>>>
>>>> std::vector<int> vec2{43, std::default_init};
>>>>
>>>> creates a vector of 43 default-initialized ints. The latter,
>>>>
>>>> std::vector<int> vec2{43};
>>>>
>>>> creates a vector of one int with the value 43. The first is spelled as
>>>> it is in order
>>>> to avoid this ambiguity, so the init_kind argument acts as an overload
>>>> resolution
>>>> selector, allowing an invocation of a constructor such as
>>>>
>>>> vector(size_t howmany, init_kind howtoinit);
>>>>
>>>
--
------=_Part_1475_6085227.1356802606872
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
I would like to see this behavior:<br><br>std::vector<int> a{10}; // =
does not use initializer list constructor. creates a vector with ten elemen=
ts<br>std::vector<int> b{10, 20, 30}; // calls initializer list const=
ructor<br>
std::vector<int> c{{10}}; // calls initializer list constructor, crea=
tes vector with the element 10<br>std::vector<int> d{std::move(b)}; /=
/ does not use initializer list constructor, calls move constructor<br>std:=
:vector<std::function<void ()>> e{}; // default constructor<br>=
std::vector<std::function<void ()>> f{std::move(e)}; // expect =
same behavior as d<br><br>Currently the last line does not compile because =
it tries to use the initializer_list constructor.<br><br>What I want is tha=
t first the compiler tries all non-initializer_list constructors, and that =
it only uses the initializer_list one if none of those work.<br><br>Current=
ly you can't use uniform initialization in generic code, because it can bre=
ak where initialization with parenthesis wouldn't break if someone uses you=
r code with an object with an initializer list constructor. Which is a sham=
e. Uniform initialization would be great for generic code.<br><br>Cheers,<b=
r><br>Malte<br><br>Am Mittwoch, 14. November 2012 12:16:36 UTC+1 schrieb Ar=
thur Tchaikovsky:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div>Hi Nicol=
<br></div><div><br></div><div>After giving it some thought I do see value i=
n your proposal. That said, I still believe that default case should be as =
minimal as possible, and only unusual behavior should be indicated.</div><d=
iv><br></div><div>Looking forward to hear from you.</div><br>On Tuesday, 13=
November 2012 17:27:11 UTC, Nicol Bolas wrote:<blockquote class=3D"gmail_=
quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddi=
ng-left:1ex"><br><br>On Tuesday, November 13, 2012 8:55:12 AM UTC-8, Arthur=
Tchaikovsky wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;marg=
in-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex">
Well, the first,
<br></blockquote>
<blockquote>std::vector<int> vec2{43, std::default_init}; <br></=
blockquote>
<blockquote>creates a vector of 43 default-initialized ints. The latter,&nb=
sp;<br></blockquote>
<blockquote>std::vector<int> vec2{43}; <br></blockquote>
<blockquote>creates a vector of one int with the value 43. <br></block=
quote><div><br></div><div>Then I have to say that this is simply bad idea. =
As for confusion, more things to learn etc. This is simply getting unwieldy=
.. If anything something like method of initialization should be done in a t=
emplate param list, for example:</div><div><br></div><div> std::vector=
<int, std::default_init> vec2(43);<br></div></blockquote><div><br>Bes=
ides the fact that this would be a breaking change (and therefore a non-sta=
rter), that's not what I'm talking about. I don't even know how we got onto=
`std::default_init` to begin with. This post was about `std::<i>value_init=
</i>`; default_init was another thread with a different purpose.<br><br>The=
purpose of this feature is to allow uniform initialization to actually be =
<i>uniform</i>. These:<br><br>std::vector<int> vec1(43); //Create a v=
ector with 43 zeros.<br>std::vector<int> vec2{43}; //Create a vector =
containing one entry.<br><br>These are not the same. In most cases, using (=
) and {} will give the same results. But not here. And this is a trap peopl=
e fall into <i>all the time.</i><br><br>That's why we need a uniform mechan=
ism for value initialization (ie: create a vector with 43 zeros) that won't=
be confused for list initialization:<br><br>std::vector<int> vec1(43=
, std::value_init); //Create a vector with 43 zeros.<br>std::vector<int&=
gt; vec2{43, std::value_init}; //Create a vector with 43 zeros.<br><br>This=
is uniform; it works the same way in both places. And that's good.<br><br>=
For backwards compatibility, we won't <i>require</i> std::value_init for th=
at constructor (and similar functions). But we will allow it.<br><br></div>=
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div>What Nicol proposes is confusi=
ng (I'm not saying that mine isn't). What is initialized by default? The ve=
ctor? The objects stored in this vector? I'm not saying that having some me=
chanism as proposed by Nicol is bad, on the contrary, but I think he didn't=
give enough thought to his idea and is simply not even half baked. Not get=
ting back at him as I more concerned with the future state of c++ than with=
his unpleasant remarks directed at me.</div></blockquote><div><br>This is =
a conversation best had <a href=3D"https://groups.google.com/a/isocpp.org/f=
orum/#%21topic/std-proposals/4BHDIXgCcL8" target=3D"_blank">in the proper t=
hread</a>. These features are orthogonal (though obviously related). Howeve=
r, the name of it, whether it's std::default_init, std::default_value, std:=
:whatever, is a bikeshed issue that shouldn't hold up the feature itself.<b=
r> </div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-le=
ft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div><br></div>On Tue=
sday, 13 November 2012 15:01:54 UTC, Ville Voutilainen wrote:<blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex">On 13 November 2012 16:57, Arthur Tchaikovsky &l=
t;<a>atch...@gmail.com</a>> wrote:
<br>>> std::vector<int> vec2{43, std::default_init};
<br>> Surely you won't have to have syntax where default needs to be spe=
cified. I
<br>> do understand other cases you mentioned like value_init, but for m=
e if I
<br>> have to specify something extra which will get me default behavior=
is simply
<br>> bad design.
<br>> I do understand that:
<br>> std::vector<int> vec2{43};//<-- this is with defaul=
t init and doesn't have
<br>> to be specified because is default
<br>
<br>Well, the first,
<br>
<br>std::vector<int> vec2{43, std::default_init};
<br>
<br>creates a vector of 43 default-initialized ints. The latter,
<br>
<br>std::vector<int> vec2{43};
<br>
<br>creates a vector of one int with the value 43. The first is spelled as
<br>it is in order
<br>to avoid this ambiguity, so the init_kind argument acts as an overload
<br>resolution
<br>selector, allowing an invocation of a constructor such as
<br>
<br>vector(size_t howmany, init_kind howtoinit);
<br></blockquote></blockquote></blockquote></blockquote>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_1475_6085227.1356802606872--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 29 Dec 2012 12:30:16 -0800 (PST)
Raw View
------=_Part_290_29700939.1356813016563
Content-Type: text/plain; charset=ISO-8859-1
On Saturday, December 29, 2012 9:36:46 AM UTC-8, maltes...@gmail.com wrote:
>
> I would like to see this behavior:
>
> std::vector<int> a{10}; // does not use initializer list constructor.
> creates a vector with ten elements
> std::vector<int> b{10, 20, 30}; // calls initializer list constructor
> std::vector<int> c{{10}}; // calls initializer list constructor, creates
> vector with the element 10
> std::vector<int> d{std::move(b)}; // does not use initializer list
> constructor, calls move constructor
> std::vector<std::function<void ()>> e{}; // default constructor
> std::vector<std::function<void ()>> f{std::move(e)}; // expect same
> behavior as d
>
> Currently the last line does not compile because it tries to use the
> initializer_list constructor.
>
> What I want is that first the compiler tries all non-initializer_list
> constructors, and that it only uses the initializer_list one if none of
> those work.
>
> Currently you can't use uniform initialization in generic code, because it
> can break where initialization with parenthesis wouldn't break if someone
> uses your code with an object with an initializer list constructor. Which
> is a shame. Uniform initialization would be great for generic code.
>
> Cheers,
>
> Malte
>
Ignoring the fact that this is a *major* breaking change and therefore a
non-starter, it also doesn't really solve the problem.
Let's say I have a vector<vector<int>>. What should this do?
vector<vector<int>> t = {{20}};
It could be use an initializer_list for both, thus creating a one-element
vector that contains a one-element vector<int>. Or it could use
initializer_list for the outer one and constructor initialization for the
inner one, thus creating a one-element vector that contains a 20 element
vector<int>. Your way would pick #2. Is there a way to make it pick #1?
vector<vector<int>> t = {{{{20}}}};
Would this force it to use initializer list construction for both? If so,
it's a bit odd for doing that, with all of those {} pairs.
The core of the problem is that uniform initialization is grammatically
tied to something else: construction via initializer_list. If there's a
conflict, only one of them can win. And that's the problem: no matter which
one we pick, *someone* will want the other one in some situation. Both
choices are legitimate, for different reasons, at different times, and
either choice will shadow someone's alternatives, thus forcing them to use
parenthesis.
It's easy to say that in "generic code", you might want to prefer regular
constructors over initializer_lists. But what if that's what you really
wanted? You could very well have a function that takes an arbitrary number
of values, all of the same type, and you want to shove them into a vector
or some other container. You shouldn't have to limit yourself to a
compile-time container like tuple.
At which point you have to stop using uniform initialization.
The problem with your solution (again, besides the fact that it's a major
breaking change and therefore a non-starter) is that you can reach
ambiguous constructs
The more I think about it, the more it's clear to me now that we need a *
language*-level solution for this. We need some way to say that a *
particular* braced-init-list should ignore initializer_list constructors.
That way, it's very clear what we're talking about.
I have absolutely no idea what that grammar would look like. It would have
to be a token sequence that is illegal currently. I was thinking something
like this:
vector<vector<int>> t = {{. 20}};
The `{.` token sequence represents a construction-braced-init-list. This
works exactly like a braced-init-list, except that non-initializer_list
constructors take priority over initializer_list constructors.
Now, it's completely obvious that this particular token sequence is
terribly broken. Consider `{.20}`; Is that a regular braced-init-list with
one element that is a double-precision 0.20? Or is that a
construction-braced-init-list with one element that is the integer 20? We
obviously could pick one over the other, but we don't want to break
people's code. Code in C++11 that used `{.20}` should still work.
No, `{.` is just an example. We would need something else. Perhaps `{^`; I
can't see that being particularly legal syntax.
--
------=_Part_290_29700939.1356813016563
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<br><br>On Saturday, December 29, 2012 9:36:46 AM UTC-8, maltes...@gmail.co=
m wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;">I would like to see th=
is behavior:<br><br>std::vector<int> a{10}; // does not use initializ=
er list constructor. creates a vector with ten elements<br>std::vector<i=
nt> b{10, 20, 30}; // calls initializer list constructor<br>
std::vector<int> c{{10}}; // calls initializer list constructor, crea=
tes vector with the element 10<br>std::vector<int> d{std::move(b)}; /=
/ does not use initializer list constructor, calls move constructor<br>std:=
:vector<std::function<void ()>> e{}; // default constructor<br>=
std::vector<std::function<void ()>> f{std::move(e)}; // expect =
same behavior as d<br><br>Currently the last line does not compile because =
it tries to use the initializer_list constructor.<br><br>What I want is tha=
t first the compiler tries all non-initializer_list constructors, and that =
it only uses the initializer_list one if none of those work.<br><br>Current=
ly you can't use uniform initialization in generic code, because it can bre=
ak where initialization with parenthesis wouldn't break if someone uses you=
r code with an object with an initializer list constructor. Which is a sham=
e. Uniform initialization would be great for generic code.<br><br>Cheers,<b=
r><br>Malte<br></blockquote><div><br>Ignoring the fact that this is a <i>ma=
jor</i> breaking change and therefore a non-starter, it also doesn't really=
solve the problem.<br><br>Let's say I have a vector<vector<int>&g=
t;. What should this do?<br><br><div class=3D"prettyprint" style=3D"backgro=
und-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-sty=
le: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"pretty=
print"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"=
styled-by-prettify">vector</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify"><</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">vector</span><span style=3D"color: #080;" class=3D"styled-by-pret=
tify"><int></span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">></span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> t </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</s=
pan><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">20</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">}};</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br></span></div></code></div><br>It could =
be use an initializer_list for both, thus creating a one-element vector tha=
t contains a one-element vector<int>. Or it could use initializer_lis=
t for the outer one and constructor initialization for the inner one, thus =
creating a one-element vector that contains a 20 element vector<int>.=
Your way would pick #2. Is there a way to make it pick #1?<br><br><div cla=
ss=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-co=
lor: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap:=
break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">vector</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">vector</span><span style=3D"=
color: #080;" 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"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: #660;" class=3D"style=
d-by-prettify">{{{{</span><span style=3D"color: #066;" class=3D"styled-by-p=
rettify">20</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>Would this force it to use initializer list c=
onstruction for both? If so, it's a bit odd for doing that, with all of tho=
se {} pairs.<br><br>The core of the problem is that uniform initialization =
is grammatically tied to something else: construction via initializer_list.=
If there's a conflict, only one of them can win. And that's the problem: n=
o matter which one we pick, <i>someone</i> will want the other one in some =
situation. Both choices are legitimate, for different reasons, at different=
times, and either choice will shadow someone's alternatives, thus forcing =
them to use parenthesis.<br><br>It's easy to say that in "generic code", yo=
u might want to prefer regular constructors over initializer_lists. But wha=
t if that's what you really wanted? You could very well have a function tha=
t takes an arbitrary number of values, all of the same type, and you want t=
o shove them into a vector or some other container. You shouldn't have to l=
imit yourself to a compile-time container like tuple.<br><br> At which=
point you have to stop using uniform initialization.</div><br>The problem =
with your solution (again, besides the fact that it's a major breaking chan=
ge and therefore a non-starter) is that you can reach ambiguous constructs<=
br><br>The more I think about it, the more it's clear to me now that we nee=
d a <i>language</i>-level solution for this. We need some way to say that a=
<i>particular</i> braced-init-list should ignore initializer_list construc=
tors. That way, it's very clear what we're talking about.<br><br>I have abs=
olutely no idea what that grammar would look like. It would have to be a to=
ken sequence that is illegal currently. I was thinking something like 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"sub=
prettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify">vect=
or</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">vector</span><=
span style=3D"color: #080;" 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"styled-by-prettify"> t </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">=3D</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"> </span><span style=3D"color: #066;" class=3D"style=
d-by-prettify">20</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">}};</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br></span></div></code></div><br>The `{.` token sequence represents a cons=
truction-braced-init-list. This works exactly like a braced-init-list, exce=
pt that non-initializer_list constructors take priority over initializer_li=
st constructors.<br><br>Now, it's completely obvious that this particular t=
oken sequence is terribly broken. Consider `{.20}`; Is that a regular brace=
d-init-list with one element that is a double-precision 0.20? Or is that a =
construction-braced-init-list with one element that is the integer 20? We o=
bviously could pick one over the other, but we don't want to break people's=
code. Code in C++11 that used `{.20}` should still work.<br><br>No, `{.` i=
s just an example. We would need something else. Perhaps `{^`; I can't see =
that being particularly legal syntax.<br>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_290_29700939.1356813016563--
.
Author: Malte Skarupke <malteskarupke@gmail.com>
Date: Sun, 30 Dec 2012 00:55:41 +0100
Raw View
--14dae9341027ae093f04d20685fe
Content-Type: text/plain; charset=ISO-8859-1
Both syntaxes would actually be unambiguous. The current one is and the
changed one would be.
The case you mentioned would be like this:
vector<vector<int>> a{{20}}; // the vector<int> contains 20 elements
vector<vector<int>> a{{{20}}}; // the vector<int> contains one element
Currently the vector<int> contains one element in both cases, and there is
no way to make it contain 20 elements using uniform initialization.
I was reading through some old standardization documents because I wanted
to figure out why the current behavior for the constructor order was
chosen. (I couldn't find it. Too many texts...) And it is just
disheartening to see that the whole reason why this was done was to find
one uniform initialization that could be used everywhere. And then that
doesn't work for templated code.
At this point you have to tell people to never use uniform initialization
in templated code. Because if you use parenthesis and the code doesn't
compile, the user can fix it by adding the required constructors to her
class. If you use curly braces and the code doesn't compile, the user can
only fix it by removing the initializer_list constructor from her class.
The latter is clearly the worse solution and often impossible, (how do you
remove the initializer_list constructor from vector<function<void ()>>?) so
the recommendation is logically to not use uniform initialization in
templated code.
I think if we want to be able to write generic code that is able to say
"just instantiate that object with the arguments given by the user" there
are two solutions:
a) break some code by changing the order in which initializer_list and
other constructors are considered. (my proposal)
b) Another new constructor syntax. (your proposal)
Honestly between these two options this is probably not going to go
anywhere, and it is truly a shame.
2012/12/29 Nicol Bolas <jmckesson@gmail.com>
>
>
> On Saturday, December 29, 2012 9:36:46 AM UTC-8, maltes...@gmail.comwrote:
>>
>> I would like to see this behavior:
>>
>> std::vector<int> a{10}; // does not use initializer list constructor.
>> creates a vector with ten elements
>> std::vector<int> b{10, 20, 30}; // calls initializer list constructor
>> std::vector<int> c{{10}}; // calls initializer list constructor, creates
>> vector with the element 10
>> std::vector<int> d{std::move(b)}; // does not use initializer list
>> constructor, calls move constructor
>> std::vector<std::function<void ()>> e{}; // default constructor
>> std::vector<std::function<void ()>> f{std::move(e)}; // expect same
>> behavior as d
>>
>> Currently the last line does not compile because it tries to use the
>> initializer_list constructor.
>>
>> What I want is that first the compiler tries all non-initializer_list
>> constructors, and that it only uses the initializer_list one if none of
>> those work.
>>
>> Currently you can't use uniform initialization in generic code, because
>> it can break where initialization with parenthesis wouldn't break if
>> someone uses your code with an object with an initializer list constructor.
>> Which is a shame. Uniform initialization would be great for generic code.
>>
>> Cheers,
>>
>> Malte
>>
>
> Ignoring the fact that this is a *major* breaking change and therefore a
> non-starter, it also doesn't really solve the problem.
>
> Let's say I have a vector<vector<int>>. What should this do?
>
> vector<vector<int>> t = {{20}};
>
> It could be use an initializer_list for both, thus creating a one-element
> vector that contains a one-element vector<int>. Or it could use
> initializer_list for the outer one and constructor initialization for the
> inner one, thus creating a one-element vector that contains a 20 element
> vector<int>. Your way would pick #2. Is there a way to make it pick #1?
>
> vector<vector<int>> t = {{{{20}}}};
>
> Would this force it to use initializer list construction for both? If so,
> it's a bit odd for doing that, with all of those {} pairs.
>
> The core of the problem is that uniform initialization is grammatically
> tied to something else: construction via initializer_list. If there's a
> conflict, only one of them can win. And that's the problem: no matter which
> one we pick, *someone* will want the other one in some situation. Both
> choices are legitimate, for different reasons, at different times, and
> either choice will shadow someone's alternatives, thus forcing them to use
> parenthesis.
>
> It's easy to say that in "generic code", you might want to prefer regular
> constructors over initializer_lists. But what if that's what you really
> wanted? You could very well have a function that takes an arbitrary number
> of values, all of the same type, and you want to shove them into a vector
> or some other container. You shouldn't have to limit yourself to a
> compile-time container like tuple.
>
> At which point you have to stop using uniform initialization.
>
> The problem with your solution (again, besides the fact that it's a major
> breaking change and therefore a non-starter) is that you can reach
> ambiguous constructs
>
> The more I think about it, the more it's clear to me now that we need a *
> language*-level solution for this. We need some way to say that a *
> particular* braced-init-list should ignore initializer_list constructors.
> That way, it's very clear what we're talking about.
>
> I have absolutely no idea what that grammar would look like. It would have
> to be a token sequence that is illegal currently. I was thinking something
> like this:
>
> vector<vector<int>> t = {{. 20}};
>
> The `{.` token sequence represents a construction-braced-init-list. This
> works exactly like a braced-init-list, except that non-initializer_list
> constructors take priority over initializer_list constructors.
>
> Now, it's completely obvious that this particular token sequence is
> terribly broken. Consider `{.20}`; Is that a regular braced-init-list with
> one element that is a double-precision 0.20? Or is that a
> construction-braced-init-list with one element that is the integer 20? We
> obviously could pick one over the other, but we don't want to break
> people's code. Code in C++11 that used `{.20}` should still work.
>
> No, `{.` is just an example. We would need something else. Perhaps `{^`; I
> can't see that being particularly legal syntax.
> --
>
>
>
>
--
--14dae9341027ae093f04d20685fe
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div>Both syntaxes would actually be unambiguous. The current one is and th=
e changed one would be.<br></div><div>The case you mentioned would be like =
this:</div><div>vector<vector<int>> a{{20}}; // the vector<i=
nt> contains 20 elements</div>
<div>vector<vector<int>> a{{{20}}}; // the vector<int> co=
ntains one element</div><div><br></div><div>Currently the vector<int>=
contains one element in both cases, and there is no way to make it contain=
20 elements using uniform initialization.</div>
<div><br></div><div>I was reading through some old standardization document=
s because I wanted to figure out why the current behavior for the construct=
or order was chosen. (I couldn't find it. Too many texts...) And it is =
just disheartening to see that the whole reason why this was done was to fi=
nd one uniform initialization that could be used everywhere. And then that =
doesn't work for templated code.</div>
<div><br></div><div>At this point you have to tell people to never use unif=
orm initialization in templated code. Because if you use parenthesis and th=
e code doesn't compile, the user can fix it by adding the required cons=
tructors to her class. If you use curly braces and the code doesn't com=
pile, the user can only fix it by removing the initializer_list constructor=
from her class.</div>
<div>The latter is clearly the worse solution and often impossible, (how do=
you remove the initializer_list constructor from vector<function<voi=
d ()>>?) so the recommendation is logically to not use uniform initia=
lization in templated code.</div>
<div><br></div><div>I think if we want to be able to write generic code tha=
t is able to say "just instantiate that object with the arguments give=
n by the user" there are two solutions:</div><div>a) break some code b=
y changing the order in which initializer_list and other constructors are c=
onsidered. (my proposal)</div>
<div>b) Another new constructor syntax. (your proposal)</div><div><br></div=
><div>Honestly between these two options this is probably not going to go a=
nywhere, and it is truly a shame.</div><div><br></div><div>2012/12/29 Nicol=
Bolas <span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" target=
=3D"_blank">jmckesson@gmail.com</a>></span><br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div class=3D"im"><br><br>On Saturday, Decem=
ber 29, 2012 9:36:46 AM UTC-8, <a href=3D"mailto:maltes...@gmail.com" targe=
t=3D"_blank">maltes...@gmail.com</a> wrote:<blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex">
I would like to see this behavior:<br><br>std::vector<int> a{10}; // =
does not use initializer list constructor. creates a vector with ten elemen=
ts<br>std::vector<int> b{10, 20, 30}; // calls initializer list const=
ructor<br>
std::vector<int> c{{10}}; // calls initializer list constructor, crea=
tes vector with the element 10<br>std::vector<int> d{std::move(b)}; /=
/ does not use initializer list constructor, calls move constructor<br>
std::vector<std::function<void ()>> e{}; // default constructor=
<br>std::vector<std::function<void ()>> f{std::move(e)}; // exp=
ect same behavior as d<br><br>Currently the last line does not compile beca=
use it tries to use the initializer_list constructor.<br>
<br>What I want is that first the compiler tries all non-initializer_list c=
onstructors, and that it only uses the initializer_list one if none of thos=
e work.<br><br>Currently you can't use uniform initialization in generi=
c code, because it can break where initialization with parenthesis wouldn&#=
39;t break if someone uses your code with an object with an initializer lis=
t constructor. Which is a shame. Uniform initialization would be great for =
generic code.<br>
<br>Cheers,<br><br>Malte<br></blockquote></div><div><br>Ignoring the fact t=
hat this is a <i>major</i> breaking change and therefore a non-starter, it =
also doesn't really solve the problem.<br><br>Let's say I have a ve=
ctor<vector<int>>. What should this do?<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>vector</span><span style=3D"color:#660"><</span><span>vector</spa=
n><span style=3D"color:#080"><int></span><span style=3D"color:#660">&=
gt;</span><span> t </span><span style=3D"color:#660">=3D</span><span> </spa=
n><span style=3D"color:#660">{{</span><span style=3D"color:#066">20</span><=
span style=3D"color:#660">}};</span><span><br>
</span></div></code></div><br>It could be use an initializer_list for both,=
thus creating a one-element vector that contains a one-element vector<i=
nt>. Or it could use initializer_list for the outer one and constructor =
initialization for the inner one, thus creating a one-element vector that c=
ontains a 20 element vector<int>. Your way would pick #2. Is there a =
way to make it pick #1?<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>vector</span><span style=3D"color:#660"><</span><span>vector</spa=
n><span style=3D"color:#080"><int></span><span style=3D"color:#660">&=
gt;</span><span> t </span><span style=3D"color:#660">=3D</span><span> </spa=
n><span style=3D"color:#660">{{{{</span><span style=3D"color:#066">20</span=
><span style=3D"color:#660">}}}};</span><span><br>
</span></div></code></div><br>Would this force it to use initializer list c=
onstruction for both? If so, it's a bit odd for doing that, with all of=
those {} pairs.<br><br>The core of the problem is that uniform initializat=
ion is grammatically tied to something else: construction via initializer_l=
ist. If there's a conflict, only one of them can win. And that's th=
e problem: no matter which one we pick, <i>someone</i> will want the other =
one in some situation. Both choices are legitimate, for different reasons, =
at different times, and either choice will shadow someone's alternative=
s, thus forcing them to use parenthesis.<br>
<br>It's easy to say that in "generic code", you might want t=
o prefer regular constructors over initializer_lists. But what if that'=
s what you really wanted? You could very well have a function that takes an=
arbitrary number of values, all of the same type, and you want to shove th=
em into a vector or some other container. You shouldn't have to limit y=
ourself to a compile-time container like tuple.<br>
<br>=A0At which point you have to stop using uniform initialization.</div><=
br>The problem with your solution (again, besides the fact that it's a =
major breaking change and therefore a non-starter) is that you can reach am=
biguous constructs<br>
<br>The more I think about it, the more it's clear to me now that we ne=
ed a <i>language</i>-level solution for this. We need some way to say that =
a <i>particular</i> braced-init-list should ignore initializer_list constru=
ctors. That way, it's very clear what we're talking about.<br>
<br>I have absolutely no idea what that grammar would look like. It would h=
ave to be a token sequence that is illegal currently. I was thinking someth=
ing like this:<br><br><div style=3D"background-color:rgb(250,250,250);borde=
r-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:brea=
k-word">
<code><div><span>vector</span><span style=3D"color:#660"><</span><span>v=
ector</span><span style=3D"color:#080"><int></span><span style=3D"col=
or:#660">></span><span> t </span><span style=3D"color:#660">=3D</span><s=
pan> </span><span style=3D"color:#660">{{.</span><span> </span><span style=
=3D"color:#066">20</span><span style=3D"color:#660">}};</span><span><br>
</span></div></code></div><br>The `{.` token sequence represents a construc=
tion-braced-init-list. This works exactly like a braced-init-list, except t=
hat non-initializer_list constructors take priority over initializer_list c=
onstructors.<br>
<br>Now, it's completely obvious that this particular token sequence is=
terribly broken. Consider `{.20}`; Is that a regular braced-init-list with=
one element that is a double-precision 0.20? Or is that a construction-bra=
ced-init-list with one element that is the integer 20? We obviously could p=
ick one over the other, but we don't want to break people's code. C=
ode in C++11 that used `{.20}` should still work.<br>
<br>No, `{.` is just an example. We would need something else. Perhaps `{^`=
; I can't see that being particularly legal syntax.<span class=3D"HOEnZ=
b"><font color=3D"#888888"><br>
-- <br>
=A0<br>
=A0<br>
=A0<br>
</font></span></blockquote></div><br>
<p></p>
-- <br />
<br />
<br />
<br />
--14dae9341027ae093f04d20685fe--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 29 Dec 2012 16:21:38 -0800 (PST)
Raw View
------=_Part_526_12138694.1356826898511
Content-Type: text/plain; charset=ISO-8859-1
On Saturday, December 29, 2012 3:55:41 PM UTC-8, Malte Skarupke wrote:
>
> Both syntaxes would actually be unambiguous. The current one is and the
> changed one would be.
> The case you mentioned would be like this:
> vector<vector<int>> a{{20}}; // the vector<int> contains 20 elements
> vector<vector<int>> a{{{20}}}; // the vector<int> contains one element
>
> Currently the vector<int> contains one element in both cases, and there is
> no way to make it contain 20 elements using uniform initialization.
>
> I was reading through some old standardization documents because I wanted
> to figure out why the current behavior for the constructor order was
> chosen. (I couldn't find it. Too many texts...) And it is just
> disheartening to see that the whole reason why this was done was to find
> one uniform initialization that could be used everywhere. And then that
> doesn't work for templated code.
>
In what way? It does exactly what it says it does in templated code.
> At this point you have to tell people to never use uniform initialization
> in templated code. Because if you use parenthesis and the code doesn't
> compile, the user can fix it by adding the required constructors to her
> class. If you use curly braces and the code doesn't compile, the user can
> only fix it by removing the initializer_list constructor from her class.
>
.... what? The problem isn't that code doesn't compile; indeed, the problem
is that it *does* compile. The problem is that doesn't necessarily do what
you wanted if what you wanted was to call a non-initializer_list
constructor *and* the braced-init-list you provide matches an
initializer_list constructor.
The latter is clearly the worse solution and often impossible, (how do you
> remove the initializer_list constructor from vector<function<void ()>>?) so
> the recommendation is logically to not use uniform initialization in
> templated code.
>
The initializer_list constructors of `vector<function<void()>>` do not
interfere with calling constructors in any way. This is completely
unambiguous:
vector<function<void()>> v = {20};
You're making a vector with 20 default-constructed entries. This *cannot*call the initializer_list constructor, because `{20}` cannot be converted
into an `initializer_list<function<void()>>`. The initializer_list
constructor does not interfere in any way, shape, or form.
This is also completely unambiguous:
vector<function<void()>> v = {{SomeVoidFunc}, {OtherVoidFunc}};
This uses the initializer_list constructor to construct a vector of 2
functions.
The only problem with `vector`'s constructors and uniform initialization is
if you use `vector<int>` or similar types:
vector<int> = {20};
This is ambiguous *only* because the initializer_list constructor for
vector<int> is of type `initializer_list<int>`, which is what `{20}`
resolves to. This interferes with the regular constructor of `vector` that
takes a `size_t`, thus masking the use of that constructor.
I think you're not fully understanding the problem. It is a non-trivial
problem, but it isn't as dire as you suggest.
> I think if we want to be able to write generic code that is able to say
> "just instantiate that object with the arguments given by the user" there
> are two solutions:
> a) break some code by changing the order in which initializer_list and
> other constructors are considered. (my proposal)
> b) Another new constructor syntax. (your proposal)
>
It's not a "new constructor syntax". It's the *same* constructor syntax
with slightly modified rules. It behaves identically except in which
constructors it prefers.
> Honestly between these two options this is probably not going to go
> anywhere, and it is truly a shame.
>
Well nothing is going to come of it if you don't believe it's going to.
a) is not happening. In order for you to convince the committee to make
such a major backwards-incompatible change, you would need to provide
serious evidence from many actual, live C++11 projects that it would be
non-disruptive to them.
b) is much more reasonable. It's far less intrusive overall. It will cause
zero backwards incompatible changes. And so forth. And it's really easy to
specify in the standard. The only real problem is convincing people that
it's an important enough issue to fix, and finding the right syntax for it.
2012/12/29 Nicol Bolas <jmck...@gmail.com <javascript:>>
>
>>
>>
>> On Saturday, December 29, 2012 9:36:46 AM UTC-8, maltes...@gmail.comwrote:
>>>
>>> I would like to see this behavior:
>>>
>>> std::vector<int> a{10}; // does not use initializer list constructor.
>>> creates a vector with ten elements
>>> std::vector<int> b{10, 20, 30}; // calls initializer list constructor
>>> std::vector<int> c{{10}}; // calls initializer list constructor, creates
>>> vector with the element 10
>>> std::vector<int> d{std::move(b)}; // does not use initializer list
>>> constructor, calls move constructor
>>> std::vector<std::function<void ()>> e{}; // default constructor
>>> std::vector<std::function<void ()>> f{std::move(e)}; // expect same
>>> behavior as d
>>>
>>> Currently the last line does not compile because it tries to use the
>>> initializer_list constructor.
>>>
>>> What I want is that first the compiler tries all non-initializer_list
>>> constructors, and that it only uses the initializer_list one if none of
>>> those work.
>>>
>>> Currently you can't use uniform initialization in generic code, because
>>> it can break where initialization with parenthesis wouldn't break if
>>> someone uses your code with an object with an initializer list constructor.
>>> Which is a shame. Uniform initialization would be great for generic code.
>>>
>>> Cheers,
>>>
>>> Malte
>>>
>>
>> Ignoring the fact that this is a *major* breaking change and therefore a
>> non-starter, it also doesn't really solve the problem.
>>
>> Let's say I have a vector<vector<int>>. What should this do?
>>
>> vector<vector<int>> t = {{20}};
>>
>> It could be use an initializer_list for both, thus creating a one-element
>> vector that contains a one-element vector<int>. Or it could use
>> initializer_list for the outer one and constructor initialization for the
>> inner one, thus creating a one-element vector that contains a 20 element
>> vector<int>. Your way would pick #2. Is there a way to make it pick #1?
>>
>> vector<vector<int>> t = {{{{20}}}};
>>
>> Would this force it to use initializer list construction for both? If so,
>> it's a bit odd for doing that, with all of those {} pairs.
>>
>> The core of the problem is that uniform initialization is grammatically
>> tied to something else: construction via initializer_list. If there's a
>> conflict, only one of them can win. And that's the problem: no matter which
>> one we pick, *someone* will want the other one in some situation. Both
>> choices are legitimate, for different reasons, at different times, and
>> either choice will shadow someone's alternatives, thus forcing them to use
>> parenthesis.
>>
>> It's easy to say that in "generic code", you might want to prefer regular
>> constructors over initializer_lists. But what if that's what you really
>> wanted? You could very well have a function that takes an arbitrary number
>> of values, all of the same type, and you want to shove them into a vector
>> or some other container. You shouldn't have to limit yourself to a
>> compile-time container like tuple.
>>
>> At which point you have to stop using uniform initialization.
>>
>> The problem with your solution (again, besides the fact that it's a major
>> breaking change and therefore a non-starter) is that you can reach
>> ambiguous constructs
>>
>> The more I think about it, the more it's clear to me now that we need a *
>> language*-level solution for this. We need some way to say that a *
>> particular* braced-init-list should ignore initializer_list
>> constructors. That way, it's very clear what we're talking about.
>>
>> I have absolutely no idea what that grammar would look like. It would
>> have to be a token sequence that is illegal currently. I was thinking
>> something like this:
>>
>> vector<vector<int>> t = {{. 20}};
>>
>> The `{.` token sequence represents a construction-braced-init-list. This
>> works exactly like a braced-init-list, except that non-initializer_list
>> constructors take priority over initializer_list constructors.
>>
>> Now, it's completely obvious that this particular token sequence is
>> terribly broken. Consider `{.20}`; Is that a regular braced-init-list with
>> one element that is a double-precision 0.20? Or is that a
>> construction-braced-init-list with one element that is the integer 20? We
>> obviously could pick one over the other, but we don't want to break
>> people's code. Code in C++11 that used `{.20}` should still work.
>>
>> No, `{.` is just an example. We would need something else. Perhaps `{^`;
>> I can't see that being particularly legal syntax.
>> --
>>
>>
>>
>>
>
>
--
------=_Part_526_12138694.1356826898511
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<br><br>On Saturday, December 29, 2012 3:55:41 PM UTC-8, Malte Skarupke wro=
te:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;"><div>Both syntaxes would ac=
tually be unambiguous. The current one is and the changed one would be.<br>=
</div><div>The case you mentioned would be like this:</div><div>vector<v=
ector<int>> a{{20}}; // the vector<int> contains 20 elements=
</div>
<div>vector<vector<int>> a{{{20}}}; // the vector<int> co=
ntains one element</div><div><br></div><div>Currently the vector<int>=
contains one element in both cases, and there is no way to make it contain=
20 elements using uniform initialization.</div>
<div><br></div><div>I was reading through some old standardization document=
s because I wanted to figure out why the current behavior for the construct=
or order was chosen. (I couldn't find it. Too many texts...) And it is just=
disheartening to see that the whole reason why this was done was to find o=
ne uniform initialization that could be used everywhere. And then that does=
n't work for templated code.</div></blockquote><div><br>In what way? It doe=
s exactly what it says it does in templated code.<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></div><div>At this point you have to tell people to never use uniform =
initialization in templated code. Because if you use parenthesis and the co=
de doesn't compile, the user can fix it by adding the required constructors=
to her class. If you use curly braces and the code doesn't compile, the us=
er can only fix it by removing the initializer_list constructor from her cl=
ass.</div></blockquote><div><br>... what? The problem isn't that code doesn=
't compile; indeed, the problem is that it <i>does</i> compile. The problem=
is that doesn't necessarily do what you wanted if what you wanted was to c=
all a non-initializer_list constructor <i>and</i> the braced-init-list you =
provide matches an initializer_list constructor.<br><br></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
#ccc solid;padding-left: 1ex;">
<div>The latter is clearly the worse solution and often impossible, (how do=
you remove the initializer_list constructor from vector<function<voi=
d ()>>?) so the recommendation is logically to not use uniform initia=
lization in templated code.</div></blockquote><div><br>The initializer_list=
constructors of `vector<function<void()>>` do not interfere wi=
th calling constructors in any way. This is completely unambiguous:<br><br>=
vector<function<void()>> v =3D {20};<br><br>You're making a vec=
tor with 20 default-constructed entries. This <i>cannot</i> call the initia=
lizer_list constructor, because `{20}` cannot be converted into an `initial=
izer_list<function<void()>>`. The initializer_list constructor =
does not interfere in any way, shape, or form.<br><br>This is also complete=
ly unambiguous:<br><br>vector<function<void()>> v =3D {{SomeVoi=
dFunc}, {OtherVoidFunc}};<br><br>This uses the initializer_list constructor=
to construct a vector of 2 functions.<br><br>The only problem with `vector=
`'s constructors and uniform initialization is if you use `vector<int>=
;` or similar types:<br><br>vector<int> =3D {20};<br><br>This is ambi=
guous <i>only</i> because the initializer_list constructor for vector<in=
t> is of type `initializer_list<int>`, which is what `{20}` resolv=
es to. This interferes with the regular constructor of `vector` that takes =
a `size_t`, thus masking the use of that constructor.<br><br>I think you're=
not fully understanding the problem. It is a non-trivial problem, but it i=
sn't as dire as you suggest.<br> </div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;">
<div></div><div>I think if we want to be able to write generic code that is=
able to say "just instantiate that object with the arguments given by the =
user" there are two solutions:</div><div>a) break some code by changing the=
order in which initializer_list and other constructors are considered. (my=
proposal)</div>
<div>b) Another new constructor syntax. (your proposal)</div></blockquote><=
div><br>It's not a "new constructor syntax". It's the <i>same</i> construct=
or syntax with slightly modified rules. It behaves identically except in wh=
ich constructors it prefers.<br> </div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div></div><div>Honestly between these two options this is pr=
obably not going to go anywhere, and it is truly a shame.</div></blockquote=
><div><br>Well nothing is going to come of it if you don't believe it's goi=
ng to.<br><br>a) is not happening. In order for you to convince the committ=
ee to make such a major backwards-incompatible change, you would need to pr=
ovide serious evidence from many actual, live C++11 projects that it would =
be non-disruptive to them.<br><br>b) is much more reasonable. It's far less=
intrusive overall. It will cause zero backwards incompatible changes. And =
so forth. And it's really easy to specify in the standard. The only real pr=
oblem is convincing people that it's an important enough issue to fix, and =
finding the right syntax for it.<br><br></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;"><div>2012/12/29 Nicol Bolas <span dir=3D"ltr"><<a href=
=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"LTHhTgpPcrgJ">j=
mck...@gmail.com</a>></span><br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div><br><br>On Saturday, December 29, 2012 =
9:36:46 AM UTC-8, <a>maltes...@gmail.com</a> wrote:<blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex">
I would like to see this behavior:<br><br>std::vector<int> a{10}; // =
does not use initializer list constructor. creates a vector with ten elemen=
ts<br>std::vector<int> b{10, 20, 30}; // calls initializer list const=
ructor<br>
std::vector<int> c{{10}}; // calls initializer list constructor, crea=
tes vector with the element 10<br>std::vector<int> d{std::move(b)}; /=
/ does not use initializer list constructor, calls move constructor<br>
std::vector<std::function<void ()>> e{}; // default constructor=
<br>std::vector<std::function<void ()>> f{std::move(e)}; // exp=
ect same behavior as d<br><br>Currently the last line does not compile beca=
use it tries to use the initializer_list constructor.<br>
<br>What I want is that first the compiler tries all non-initializer_list c=
onstructors, and that it only uses the initializer_list one if none of thos=
e work.<br><br>Currently you can't use uniform initialization in generic co=
de, because it can break where initialization with parenthesis wouldn't bre=
ak if someone uses your code with an object with an initializer list constr=
uctor. Which is a shame. Uniform initialization would be great for generic =
code.<br>
<br>Cheers,<br><br>Malte<br></blockquote></div><div><br>Ignoring the fact t=
hat this is a <i>major</i> breaking change and therefore a non-starter, it =
also doesn't really solve the problem.<br><br>Let's say I have a vector<=
vector<int>>. What should this do?<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>vector</span><span style=3D"color:#660"><</span><span>vector</spa=
n><span style=3D"color:#080"><int></span><span style=3D"color:#660">&=
gt;</span><span> t </span><span style=3D"color:#660">=3D</span><span> </spa=
n><span style=3D"color:#660">{{</span><span style=3D"color:#066">20</span><=
span style=3D"color:#660">}};</span><span><br>
</span></div></code></div><br>It could be use an initializer_list for both,=
thus creating a one-element vector that contains a one-element vector<i=
nt>. Or it could use initializer_list for the outer one and constructor =
initialization for the inner one, thus creating a one-element vector that c=
ontains a 20 element vector<int>. Your way would pick #2. Is there a =
way to make it pick #1?<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>vector</span><span style=3D"color:#660"><</span><span>vector</spa=
n><span style=3D"color:#080"><int></span><span style=3D"color:#660">&=
gt;</span><span> t </span><span style=3D"color:#660">=3D</span><span> </spa=
n><span style=3D"color:#660">{{{{</span><span style=3D"color:#066">20</span=
><span style=3D"color:#660">}}}};</span><span><br>
</span></div></code></div><br>Would this force it to use initializer list c=
onstruction for both? If so, it's a bit odd for doing that, with all of tho=
se {} pairs.<br><br>The core of the problem is that uniform initialization =
is grammatically tied to something else: construction via initializer_list.=
If there's a conflict, only one of them can win. And that's the problem: n=
o matter which one we pick, <i>someone</i> will want the other one in some =
situation. Both choices are legitimate, for different reasons, at different=
times, and either choice will shadow someone's alternatives, thus forcing =
them to use parenthesis.<br>
<br>It's easy to say that in "generic code", you might want to prefer regul=
ar constructors over initializer_lists. But what if that's what you really =
wanted? You could very well have a function that takes an arbitrary number =
of values, all of the same type, and you want to shove them into a vector o=
r some other container. You shouldn't have to limit yourself to a compile-t=
ime container like tuple.<br>
<br> At which point you have to stop using uniform initialization.</di=
v><br>The problem with your solution (again, besides the fact that it's a m=
ajor breaking change and therefore a non-starter) is that you can reach amb=
iguous constructs<br>
<br>The more I think about it, the more it's clear to me now that we need a=
<i>language</i>-level solution for this. We need some way to say that a <i=
>particular</i> braced-init-list should ignore initializer_list constructor=
s. That way, it's very clear what we're talking about.<br>
<br>I have absolutely no idea what that grammar would look like. It would h=
ave to be a token sequence that is illegal currently. I was thinking someth=
ing like this:<br><br><div style=3D"background-color:rgb(250,250,250);borde=
r-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:brea=
k-word">
<code><div><span>vector</span><span style=3D"color:#660"><</span><span>v=
ector</span><span style=3D"color:#080"><int></span><span style=3D"col=
or:#660">></span><span> t </span><span style=3D"color:#660">=3D</span><s=
pan> </span><span style=3D"color:#660">{{.</span><span> </span><span style=
=3D"color:#066">20</span><span style=3D"color:#660">}};</span><span><br>
</span></div></code></div><br>The `{.` token sequence represents a construc=
tion-braced-init-list. This works exactly like a braced-init-list, except t=
hat non-initializer_list constructors take priority over initializer_list c=
onstructors.<br>
<br>Now, it's completely obvious that this particular token sequence is ter=
ribly broken. Consider `{.20}`; Is that a regular braced-init-list with one=
element that is a double-precision 0.20? Or is that a construction-braced-=
init-list with one element that is the integer 20? We obviously could pick =
one over the other, but we don't want to break people's code. Code in C++11=
that used `{.20}` should still work.<br>
<br>No, `{.` is just an example. We would need something else. Perhaps `{^`=
; I can't see that being particularly legal syntax.<span><font color=3D"#88=
8888"><br>
-- <br>
<br>
<br>
<br>
</font></span></blockquote></div><br>
</blockquote>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_526_12138694.1356826898511--
.
Author: Malte Skarupke <malteskarupke@gmail.com>
Date: Sun, 30 Dec 2012 12:49:52 +0100
Raw View
--f46d04389415d235d004d2107ff6
Content-Type: text/plain; charset=ISO-8859-1
It actually seems like my example from above should compile:
vector<function<void ()>> e{}; // default constructor
vector<function<void ()>> f{move(e)}; // doesn't compile
Currently it does not compile in either GCC or Clang, but it seems to
compile starting at GCC 4.8 and Clang 3.3. I thought that the standard made
this impossible by saying that initializer_list constructors should be
considered first, and as far as the function declarations are concerned,
you can convert a vector to a function<void ()>. Only if you actually
compile the function will you notice that a vector doesn't match, at which
point it's too late to try other overloads.
Since this will apparently start to compile just fine in newer versions of
the compilers, that actually makes this less of a problem than I thought. I
would be interested though in how they fixed it. If it was a fix in the
library by doing SFINAE on std::function, then this problem will just
re-occur for other types.
In any case I don't think that we need breaking changes any more.
I am still not a big fan of allowing a new syntax. Then you would introduce
the problem that your templated code would have to be used differently
depending on which constructor syntax you use. If I use {} then the user
would have to do different behavior than if I use {.} (or whatever it would
end up to be). And it's not really realistic to expect the user to know
which syntax you use somewhere internally. (for example try to find out if
vector<T>::emplace_back uses () or {}. It is hidden pretty well)
Which is by the way another reason to never use {} syntax in templated
code. Even if it is unambiguous it will probably be unexpected.
Malte
2012/12/30 Nicol Bolas <jmckesson@gmail.com>
>
>
> On Saturday, December 29, 2012 3:55:41 PM UTC-8, Malte Skarupke wrote:
>>
>> Both syntaxes would actually be unambiguous. The current one is and the
>> changed one would be.
>> The case you mentioned would be like this:
>> vector<vector<int>> a{{20}}; // the vector<int> contains 20 elements
>> vector<vector<int>> a{{{20}}}; // the vector<int> contains one element
>>
>> Currently the vector<int> contains one element in both cases, and there
>> is no way to make it contain 20 elements using uniform initialization.
>>
>> I was reading through some old standardization documents because I wanted
>> to figure out why the current behavior for the constructor order was
>> chosen. (I couldn't find it. Too many texts...) And it is just
>> disheartening to see that the whole reason why this was done was to find
>> one uniform initialization that could be used everywhere. And then that
>> doesn't work for templated code.
>>
>
> In what way? It does exactly what it says it does in templated code.
>
>
>> At this point you have to tell people to never use uniform initialization
>> in templated code. Because if you use parenthesis and the code doesn't
>> compile, the user can fix it by adding the required constructors to her
>> class. If you use curly braces and the code doesn't compile, the user can
>> only fix it by removing the initializer_list constructor from her class.
>>
>
> ... what? The problem isn't that code doesn't compile; indeed, the problem
> is that it *does* compile. The problem is that doesn't necessarily do
> what you wanted if what you wanted was to call a non-initializer_list
> constructor *and* the braced-init-list you provide matches an
> initializer_list constructor.
>
> The latter is clearly the worse solution and often impossible, (how do you
>> remove the initializer_list constructor from vector<function<void ()>>?) so
>> the recommendation is logically to not use uniform initialization in
>> templated code.
>>
>
> The initializer_list constructors of `vector<function<void()>>` do not
> interfere with calling constructors in any way. This is completely
> unambiguous:
>
> vector<function<void()>> v = {20};
>
> You're making a vector with 20 default-constructed entries. This *cannot*call the initializer_list constructor, because `{20}` cannot be converted
> into an `initializer_list<function<void()>>`. The initializer_list
> constructor does not interfere in any way, shape, or form.
>
> This is also completely unambiguous:
>
> vector<function<void()>> v = {{SomeVoidFunc}, {OtherVoidFunc}};
>
> This uses the initializer_list constructor to construct a vector of 2
> functions.
>
> The only problem with `vector`'s constructors and uniform initialization
> is if you use `vector<int>` or similar types:
>
> vector<int> = {20};
>
> This is ambiguous *only* because the initializer_list constructor for
> vector<int> is of type `initializer_list<int>`, which is what `{20}`
> resolves to. This interferes with the regular constructor of `vector` that
> takes a `size_t`, thus masking the use of that constructor.
>
> I think you're not fully understanding the problem. It is a non-trivial
> problem, but it isn't as dire as you suggest.
>
>
>> I think if we want to be able to write generic code that is able to say
>> "just instantiate that object with the arguments given by the user" there
>> are two solutions:
>> a) break some code by changing the order in which initializer_list and
>> other constructors are considered. (my proposal)
>> b) Another new constructor syntax. (your proposal)
>>
>
> It's not a "new constructor syntax". It's the *same* constructor syntax
> with slightly modified rules. It behaves identically except in which
> constructors it prefers.
>
>
>> Honestly between these two options this is probably not going to go
>> anywhere, and it is truly a shame.
>>
>
> Well nothing is going to come of it if you don't believe it's going to.
>
> a) is not happening. In order for you to convince the committee to make
> such a major backwards-incompatible change, you would need to provide
> serious evidence from many actual, live C++11 projects that it would be
> non-disruptive to them.
>
> b) is much more reasonable. It's far less intrusive overall. It will cause
> zero backwards incompatible changes. And so forth. And it's really easy to
> specify in the standard. The only real problem is convincing people that
> it's an important enough issue to fix, and finding the right syntax for it.
>
> 2012/12/29 Nicol Bolas <jmck...@gmail.com>
>>
>>
>>>
>>> On Saturday, December 29, 2012 9:36:46 AM UTC-8, maltes...@gmail.comwrote:
>>>>
>>>> I would like to see this behavior:
>>>>
>>>> std::vector<int> a{10}; // does not use initializer list constructor.
>>>> creates a vector with ten elements
>>>> std::vector<int> b{10, 20, 30}; // calls initializer list constructor
>>>> std::vector<int> c{{10}}; // calls initializer list constructor,
>>>> creates vector with the element 10
>>>> std::vector<int> d{std::move(b)}; // does not use initializer list
>>>> constructor, calls move constructor
>>>> std::vector<std::function<void ()>> e{}; // default constructor
>>>> std::vector<std::function<void ()>> f{std::move(e)}; // expect same
>>>> behavior as d
>>>>
>>>> Currently the last line does not compile because it tries to use the
>>>> initializer_list constructor.
>>>>
>>>> What I want is that first the compiler tries all non-initializer_list
>>>> constructors, and that it only uses the initializer_list one if none of
>>>> those work.
>>>>
>>>> Currently you can't use uniform initialization in generic code, because
>>>> it can break where initialization with parenthesis wouldn't break if
>>>> someone uses your code with an object with an initializer list constructor.
>>>> Which is a shame. Uniform initialization would be great for generic code.
>>>>
>>>> Cheers,
>>>>
>>>> Malte
>>>>
>>>
>>> Ignoring the fact that this is a *major* breaking change and therefore
>>> a non-starter, it also doesn't really solve the problem.
>>>
>>> Let's say I have a vector<vector<int>>. What should this do?
>>>
>>> vector<vector<int>> t = {{20}};
>>>
>>> It could be use an initializer_list for both, thus creating a
>>> one-element vector that contains a one-element vector<int>. Or it could use
>>> initializer_list for the outer one and constructor initialization for the
>>> inner one, thus creating a one-element vector that contains a 20 element
>>> vector<int>. Your way would pick #2. Is there a way to make it pick #1?
>>>
>>> vector<vector<int>> t = {{{{20}}}};
>>>
>>> Would this force it to use initializer list construction for both? If
>>> so, it's a bit odd for doing that, with all of those {} pairs.
>>>
>>> The core of the problem is that uniform initialization is grammatically
>>> tied to something else: construction via initializer_list. If there's a
>>> conflict, only one of them can win. And that's the problem: no matter which
>>> one we pick, *someone* will want the other one in some situation. Both
>>> choices are legitimate, for different reasons, at different times, and
>>> either choice will shadow someone's alternatives, thus forcing them to use
>>> parenthesis.
>>>
>>> It's easy to say that in "generic code", you might want to prefer
>>> regular constructors over initializer_lists. But what if that's what you
>>> really wanted? You could very well have a function that takes an arbitrary
>>> number of values, all of the same type, and you want to shove them into a
>>> vector or some other container. You shouldn't have to limit yourself to a
>>> compile-time container like tuple.
>>>
>>> At which point you have to stop using uniform initialization.
>>>
>>> The problem with your solution (again, besides the fact that it's a
>>> major breaking change and therefore a non-starter) is that you can reach
>>> ambiguous constructs
>>>
>>> The more I think about it, the more it's clear to me now that we need a
>>> *language*-level solution for this. We need some way to say that a *
>>> particular* braced-init-list should ignore initializer_list
>>> constructors. That way, it's very clear what we're talking about.
>>>
>>> I have absolutely no idea what that grammar would look like. It would
>>> have to be a token sequence that is illegal currently. I was thinking
>>> something like this:
>>>
>>> vector<vector<int>> t = {{. 20}};
>>>
>>> The `{.` token sequence represents a construction-braced-init-list. This
>>> works exactly like a braced-init-list, except that non-initializer_list
>>> constructors take priority over initializer_list constructors.
>>>
>>> Now, it's completely obvious that this particular token sequence is
>>> terribly broken. Consider `{.20}`; Is that a regular braced-init-list with
>>> one element that is a double-precision 0.20? Or is that a
>>> construction-braced-init-list with one element that is the integer 20? We
>>> obviously could pick one over the other, but we don't want to break
>>> people's code. Code in C++11 that used `{.20}` should still work.
>>>
>>> No, `{.` is just an example. We would need something else. Perhaps `{^`;
>>> I can't see that being particularly legal syntax.
>>> --
>>>
>>>
>>>
>>>
>>
>> --
>
>
>
>
--
--f46d04389415d235d004d2107ff6
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div>It actually seems like my example from above should compile:<br></div>=
<div><br>vector<function<void ()>> e{}; // default constructor<=
br>vector<function<void ()>> f{move(e)}; // doesn't compile=
</div>
<div><br></div><div>Currently it does not compile in either GCC or Clang, b=
ut it seems to compile starting at GCC 4.8 and Clang 3.3. I thought that th=
e standard made this impossible by saying that initializer_list constructor=
s should be considered first, and as far as the function declarations are c=
oncerned, you can convert a vector to a function<void ()>. Only if yo=
u actually compile the function will you notice that a vector doesn't m=
atch, at which point it's too late to try other overloads.</div>
<div><br></div><div>Since this will apparently start to compile just fine i=
n newer versions of the compilers, that actually makes this less of a probl=
em than I thought. I would be interested though in how they fixed it. If it=
was a fix in the library by doing SFINAE on std::function, then this probl=
em will just re-occur for other types.</div>
<div><br></div><div>In any case I don't think that we need breaking cha=
nges any more.</div><div><br></div><div>I am still not a big fan of allowin=
g a new syntax. Then you would introduce the problem that your templated co=
de would have to be used differently depending on which constructor syntax =
you use. If I use {} then the user would have to do different behavior than=
if I use {.} (or whatever it would end up to be). And it's not really =
realistic to expect the user to know which syntax you use somewhere interna=
lly. (for example try to find out if vector<T>::emplace_back uses () =
or {}. It is hidden pretty well)</div>
<div>Which is by the way another reason to never use {} syntax in templated=
code. Even if it is unambiguous it will probably be unexpected.</div><div>=
<br></div><div>Malte</div><br><div class=3D"gmail_quote">2012/12/30 Nicol B=
olas <span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" target=3D=
"_blank">jmckesson@gmail.com</a>></span><br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div class=3D"im"><br><br>On Saturday, Decem=
ber 29, 2012 3:55:41 PM UTC-8, Malte Skarupke wrote:<blockquote class=3D"gm=
ail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;p=
adding-left:1ex">
<div>Both syntaxes would actually be unambiguous. The current one is and th=
e changed one would be.<br></div><div>The case you mentioned would be like =
this:</div><div>vector<vector<int>> a{{20}}; // the vector<i=
nt> contains 20 elements</div>
<div>vector<vector<int>> a{{{20}}}; // the vector<int> co=
ntains one element</div><div><br></div><div>Currently the vector<int>=
contains one element in both cases, and there is no way to make it contain=
20 elements using uniform initialization.</div>
<div><br></div><div>I was reading through some old standardization document=
s because I wanted to figure out why the current behavior for the construct=
or order was chosen. (I couldn't find it. Too many texts...) And it is =
just disheartening to see that the whole reason why this was done was to fi=
nd one uniform initialization that could be used everywhere. And then that =
doesn't work for templated code.</div>
</blockquote></div><div><br>In what way? It does exactly what it says it do=
es in templated code.<br>=A0</div><div class=3D"im"><blockquote class=3D"gm=
ail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;p=
adding-left:1ex">
<div>At this point you have to tell people to never use uniform initializat=
ion in templated code. Because if you use parenthesis and the code doesn=
9;t compile, the user can fix it by adding the required constructors to her=
class. If you use curly braces and the code doesn't compile, the user =
can only fix it by removing the initializer_list constructor from her class=
..</div>
</blockquote></div><div><br>... what? The problem isn't that code doesn=
't compile; indeed, the problem is that it <i>does</i> compile. The pro=
blem is that doesn't necessarily do what you wanted if what you wanted =
was to call a non-initializer_list constructor <i>and</i> the braced-init-l=
ist you provide matches an initializer_list constructor.<br>
<br></div><div class=3D"im"><blockquote class=3D"gmail_quote" style=3D"marg=
in:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
<div>The latter is clearly the worse solution and often impossible, (how do=
you remove the initializer_list constructor from vector<function<voi=
d ()>>?) so the recommendation is logically to not use uniform initia=
lization in templated code.</div>
</blockquote></div><div><br>The initializer_list constructors of `vector<=
;function<void()>>` do not interfere with calling constructors in =
any way. This is completely unambiguous:<br><br>vector<function<void(=
)>> v =3D {20};<br>
<br>You're making a vector with 20 default-constructed entries. This <i=
>cannot</i> call the initializer_list constructor, because `{20}` cannot be=
converted into an `initializer_list<function<void()>>`. The in=
itializer_list constructor does not interfere in any way, shape, or form.<b=
r>
<br>This is also completely unambiguous:<br><br>vector<function<void(=
)>> v =3D {{SomeVoidFunc}, {OtherVoidFunc}};<br><br>This uses the ini=
tializer_list constructor to construct a vector of 2 functions.<br><br>The =
only problem with `vector`'s constructors and uniform initialization is=
if you use `vector<int>` or similar types:<br>
<br>vector<int> =3D {20};<br><br>This is ambiguous <i>only</i> becaus=
e the initializer_list constructor for vector<int> is of type `initia=
lizer_list<int>`, which is what `{20}` resolves to. This interferes w=
ith the regular constructor of `vector` that takes a `size_t`, thus masking=
the use of that constructor.<br>
<br>I think you're not fully understanding the problem. It is a non-tri=
vial problem, but it isn't as dire as you suggest.<br>=A0</div><div cla=
ss=3D"im"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0=
..8ex;border-left:1px #ccc solid;padding-left:1ex">
<div>I think if we want to be able to write generic code that is able to sa=
y "just instantiate that object with the arguments given by the user&q=
uot; there are two solutions:</div><div>a) break some code by changing the =
order in which initializer_list and other constructors are considered. (my =
proposal)</div>
<div>b) Another new constructor syntax. (your proposal)</div></blockquote><=
/div><div><br>It's not a "new constructor syntax". It's t=
he <i>same</i> constructor syntax with slightly modified rules. It behaves =
identically except in which constructors it prefers.<br>
=A0</div><div class=3D"im"><blockquote class=3D"gmail_quote" style=3D"margi=
n:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div>Hon=
estly between these two options this is probably not going to go anywhere, =
and it is truly a shame.</div>
</blockquote></div><div><br>Well nothing is going to come of it if you don&=
#39;t believe it's going to.<br><br>a) is not happening. In order for y=
ou to convince the committee to make such a major backwards-incompatible ch=
ange, you would need to provide serious evidence from many actual, live C++=
11 projects that it would be non-disruptive to them.<br>
<br>b) is much more reasonable. It's far less intrusive overall. It wil=
l cause zero backwards incompatible changes. And so forth. And it's rea=
lly easy to specify in the standard. The only real problem is convincing pe=
ople that it's an important enough issue to fix, and finding the right =
syntax for it.<br>
<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0=
..8ex;border-left:1px #ccc solid;padding-left:1ex"><div>2012/12/29 Nicol Bol=
as <span dir=3D"ltr"><<a>jmck...@gmail.com</a>></span><div><div class=
=3D"h5">
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div><br><br>On Saturday, December 29, 2012 =
9:36:46 AM UTC-8, <a>maltes...@gmail.com</a> wrote:<blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex">
I would like to see this behavior:<br><br>std::vector<int> a{10}; // =
does not use initializer list constructor. creates a vector with ten elemen=
ts<br>std::vector<int> b{10, 20, 30}; // calls initializer list const=
ructor<br>
std::vector<int> c{{10}}; // calls initializer list constructor, crea=
tes vector with the element 10<br>std::vector<int> d{std::move(b)}; /=
/ does not use initializer list constructor, calls move constructor<br>
std::vector<std::function<void ()>> e{}; // default constructor=
<br>std::vector<std::function<void ()>> f{std::move(e)}; // exp=
ect same behavior as d<br><br>Currently the last line does not compile beca=
use it tries to use the initializer_list constructor.<br>
<br>What I want is that first the compiler tries all non-initializer_list c=
onstructors, and that it only uses the initializer_list one if none of thos=
e work.<br><br>Currently you can't use uniform initialization in generi=
c code, because it can break where initialization with parenthesis wouldn&#=
39;t break if someone uses your code with an object with an initializer lis=
t constructor. Which is a shame. Uniform initialization would be great for =
generic code.<br>
<br>Cheers,<br><br>Malte<br></blockquote></div><div><br>Ignoring the fact t=
hat this is a <i>major</i> breaking change and therefore a non-starter, it =
also doesn't really solve the problem.<br><br>Let's say I have a ve=
ctor<vector<int>>. What should this do?<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>vector</span><span style=3D"color:#660"><</span><span>vector</spa=
n><span style=3D"color:#080"><int></span><span style=3D"color:#660">&=
gt;</span><span> t </span><span style=3D"color:#660">=3D</span><span> </spa=
n><span style=3D"color:#660">{{</span><span style=3D"color:#066">20</span><=
span style=3D"color:#660">}};</span><span><br>
</span></div></code></div><br>It could be use an initializer_list for both,=
thus creating a one-element vector that contains a one-element vector<i=
nt>. Or it could use initializer_list for the outer one and constructor =
initialization for the inner one, thus creating a one-element vector that c=
ontains a 20 element vector<int>. Your way would pick #2. Is there a =
way to make it pick #1?<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>vector</span><span style=3D"color:#660"><</span><span>vector</spa=
n><span style=3D"color:#080"><int></span><span style=3D"color:#660">&=
gt;</span><span> t </span><span style=3D"color:#660">=3D</span><span> </spa=
n><span style=3D"color:#660">{{{{</span><span style=3D"color:#066">20</span=
><span style=3D"color:#660">}}}};</span><span><br>
</span></div></code></div><br>Would this force it to use initializer list c=
onstruction for both? If so, it's a bit odd for doing that, with all of=
those {} pairs.<br><br>The core of the problem is that uniform initializat=
ion is grammatically tied to something else: construction via initializer_l=
ist. If there's a conflict, only one of them can win. And that's th=
e problem: no matter which one we pick, <i>someone</i> will want the other =
one in some situation. Both choices are legitimate, for different reasons, =
at different times, and either choice will shadow someone's alternative=
s, thus forcing them to use parenthesis.<br>
<br>It's easy to say that in "generic code", you might want t=
o prefer regular constructors over initializer_lists. But what if that'=
s what you really wanted? You could very well have a function that takes an=
arbitrary number of values, all of the same type, and you want to shove th=
em into a vector or some other container. You shouldn't have to limit y=
ourself to a compile-time container like tuple.<br>
<br>=A0At which point you have to stop using uniform initialization.</div><=
br>The problem with your solution (again, besides the fact that it's a =
major breaking change and therefore a non-starter) is that you can reach am=
biguous constructs<br>
<br>The more I think about it, the more it's clear to me now that we ne=
ed a <i>language</i>-level solution for this. We need some way to say that =
a <i>particular</i> braced-init-list should ignore initializer_list constru=
ctors. That way, it's very clear what we're talking about.<br>
<br>I have absolutely no idea what that grammar would look like. It would h=
ave to be a token sequence that is illegal currently. I was thinking someth=
ing like this:<br><br><div style=3D"background-color:rgb(250,250,250);borde=
r-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:brea=
k-word">
<code><div><span>vector</span><span style=3D"color:#660"><</span><span>v=
ector</span><span style=3D"color:#080"><int></span><span style=3D"col=
or:#660">></span><span> t </span><span style=3D"color:#660">=3D</span><s=
pan> </span><span style=3D"color:#660">{{.</span><span> </span><span style=
=3D"color:#066">20</span><span style=3D"color:#660">}};</span><span><br>
</span></div></code></div><br>The `{.` token sequence represents a construc=
tion-braced-init-list. This works exactly like a braced-init-list, except t=
hat non-initializer_list constructors take priority over initializer_list c=
onstructors.<br>
<br>Now, it's completely obvious that this particular token sequence is=
terribly broken. Consider `{.20}`; Is that a regular braced-init-list with=
one element that is a double-precision 0.20? Or is that a construction-bra=
ced-init-list with one element that is the integer 20? We obviously could p=
ick one over the other, but we don't want to break people's code. C=
ode in C++11 that used `{.20}` should still work.<br>
<br>No, `{.` is just an example. We would need something else. Perhaps `{^`=
; I can't see that being particularly legal syntax.<span><font color=3D=
"#888888"><br>
-- <br>
=A0<br>
=A0<br>
=A0<br>
</font></span></blockquote></div></div></div><br>
</blockquote>
-- <br>
=A0<br>
=A0<br>
=A0<br>
</blockquote></div><br>
<p></p>
-- <br />
<br />
<br />
<br />
--f46d04389415d235d004d2107ff6--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 30 Dec 2012 08:51:06 -0800 (PST)
Raw View
------=_Part_171_15029111.1356886266628
Content-Type: text/plain; charset=ISO-8859-1
On Sunday, December 30, 2012 3:49:52 AM UTC-8, Malte Skarupke wrote:
>
> It actually seems like my example from above should compile:
>
> vector<function<void ()>> e{}; // default constructor
> vector<function<void ()>> f{move(e)}; // doesn't compile
>
> Currently it does not compile in either GCC or Clang, but it seems to
> compile starting at GCC 4.8 and Clang 3.3. I thought that the standard made
> this impossible by saying that initializer_list constructors should be
> considered first, and as far as the function declarations are concerned,
> you can convert a vector to a function<void ()>.
>
Only if you actually compile the function will you notice that a vector
> doesn't match, at which point it's too late to try other overloads.
>
> Since this will apparently start to compile just fine in newer versions of
> the compilers, that actually makes this less of a problem than I thought. I
> would be interested though in how they fixed it. If it was a fix in the
> library by doing SFINAE on std::function, then this problem will just
> re-occur for other types.
>
> In any case I don't think that we need breaking changes any more.
>
> I am still not a big fan of allowing a new syntax. Then you would
> introduce the problem that your templated code would have to be used
> differently depending on which constructor syntax you use. If I use {} then
> the user would have to do different behavior than if I use {.}
>
What user will need to "do different behavior?" I don't understand your
concern.
> (or whatever it would end up to be). And it's not really realistic to
> expect the user to know which syntax you use somewhere internally.
>
The user *should not care* what you use internally. They should develop
their classes according to whatever concept your code requires (just like
in runtime-polymorphism, they implement classes based on a prototype. The
base class). Your template code, in turn, should be developed according to
the same concept.
If you are implementing a template that takes a type T which shall be
CopyConstructable, then this expression:
T t{T{}};
may violate the concept constraint. However, this expression, under the
rules I propose,:
T t{^ T{}};
will not violate the concept constraint because it will check
non-initializer_list constructors first. If your conceptual constraint on T
includes an initializer_list<int> constructor, then you should expect this:
T t{10};
to invoke the initializer_list<int> constructor. Similarly, if the concept
constraint says that T has an initializer_list<T::value_type> constructor,
then you should expect this to call that constructor:
T t{T::value_type(...)};
It will call the initializer_list constructor even if T has a
T(T::value_type) constructor.
It's all about matching expectations. Your template code expects certain
things from user code. Therefore, user code should conform to them. As long
as both sides understand what the rules are, everything should be fine.
(for example try to find out if vector<T>::emplace_back uses () or {}. It
> is hidden pretty well)
>
That makes absolutely no sense. {} is for *initialization*. `emplace_back`
is a *function call*. You would never use it there. You could use it for
one of the function's *arguments*, (though it'll be interpreted as an
initializer_list, since it's piped through a template parameter) but that's
different from using it for the function itself. Which you can't do.
The whole point of uniform initialization is that it's *initialization.*
> Which is by the way another reason to never use {} syntax in templated
> code. Even if it is unambiguous it will probably be unexpected.
>
Unexpected by whom?
>
> Malte
>
> 2012/12/30 Nicol Bolas <jmck...@gmail.com <javascript:>>
>
>>
>>
>> On Saturday, December 29, 2012 3:55:41 PM UTC-8, Malte Skarupke wrote:
>>>
>>> Both syntaxes would actually be unambiguous. The current one is and the
>>> changed one would be.
>>> The case you mentioned would be like this:
>>> vector<vector<int>> a{{20}}; // the vector<int> contains 20 elements
>>> vector<vector<int>> a{{{20}}}; // the vector<int> contains one element
>>>
>>> Currently the vector<int> contains one element in both cases, and there
>>> is no way to make it contain 20 elements using uniform initialization.
>>>
>>> I was reading through some old standardization documents because I
>>> wanted to figure out why the current behavior for the constructor order was
>>> chosen. (I couldn't find it. Too many texts...) And it is just
>>> disheartening to see that the whole reason why this was done was to find
>>> one uniform initialization that could be used everywhere. And then that
>>> doesn't work for templated code.
>>>
>>
>> In what way? It does exactly what it says it does in templated code.
>>
>>
>>> At this point you have to tell people to never use uniform
>>> initialization in templated code. Because if you use parenthesis and the
>>> code doesn't compile, the user can fix it by adding the required
>>> constructors to her class. If you use curly braces and the code doesn't
>>> compile, the user can only fix it by removing the initializer_list
>>> constructor from her class.
>>>
>>
>> ... what? The problem isn't that code doesn't compile; indeed, the
>> problem is that it *does* compile. The problem is that doesn't
>> necessarily do what you wanted if what you wanted was to call a
>> non-initializer_list constructor *and* the braced-init-list you provide
>> matches an initializer_list constructor.
>>
>> The latter is clearly the worse solution and often impossible, (how do
>>> you remove the initializer_list constructor from vector<function<void
>>> ()>>?) so the recommendation is logically to not use uniform initialization
>>> in templated code.
>>>
>>
>> The initializer_list constructors of `vector<function<void()>>` do not
>> interfere with calling constructors in any way. This is completely
>> unambiguous:
>>
>> vector<function<void()>> v = {20};
>>
>> You're making a vector with 20 default-constructed entries. This *cannot*call the initializer_list constructor, because `{20}` cannot be converted
>> into an `initializer_list<function<void()>>`. The initializer_list
>> constructor does not interfere in any way, shape, or form.
>>
>> This is also completely unambiguous:
>>
>> vector<function<void()>> v = {{SomeVoidFunc}, {OtherVoidFunc}};
>>
>> This uses the initializer_list constructor to construct a vector of 2
>> functions.
>>
>> The only problem with `vector`'s constructors and uniform initialization
>> is if you use `vector<int>` or similar types:
>>
>> vector<int> = {20};
>>
>> This is ambiguous *only* because the initializer_list constructor for
>> vector<int> is of type `initializer_list<int>`, which is what `{20}`
>> resolves to. This interferes with the regular constructor of `vector` that
>> takes a `size_t`, thus masking the use of that constructor.
>>
>> I think you're not fully understanding the problem. It is a non-trivial
>> problem, but it isn't as dire as you suggest.
>>
>>
>>> I think if we want to be able to write generic code that is able to say
>>> "just instantiate that object with the arguments given by the user" there
>>> are two solutions:
>>> a) break some code by changing the order in which initializer_list and
>>> other constructors are considered. (my proposal)
>>> b) Another new constructor syntax. (your proposal)
>>>
>>
>> It's not a "new constructor syntax". It's the *same* constructor syntax
>> with slightly modified rules. It behaves identically except in which
>> constructors it prefers.
>>
>>
>>> Honestly between these two options this is probably not going to go
>>> anywhere, and it is truly a shame.
>>>
>>
>> Well nothing is going to come of it if you don't believe it's going to.
>>
>> a) is not happening. In order for you to convince the committee to make
>> such a major backwards-incompatible change, you would need to provide
>> serious evidence from many actual, live C++11 projects that it would be
>> non-disruptive to them.
>>
>> b) is much more reasonable. It's far less intrusive overall. It will
>> cause zero backwards incompatible changes. And so forth. And it's really
>> easy to specify in the standard. The only real problem is convincing people
>> that it's an important enough issue to fix, and finding the right syntax
>> for it.
>>
>> 2012/12/29 Nicol Bolas <jmck...@gmail.com>
>>>
>>>
>>>>
>>>> On Saturday, December 29, 2012 9:36:46 AM UTC-8, maltes...@gmail.comwrote:
>>>>>
>>>>> I would like to see this behavior:
>>>>>
>>>>> std::vector<int> a{10}; // does not use initializer list constructor.
>>>>> creates a vector with ten elements
>>>>> std::vector<int> b{10, 20, 30}; // calls initializer list constructor
>>>>> std::vector<int> c{{10}}; // calls initializer list constructor,
>>>>> creates vector with the element 10
>>>>> std::vector<int> d{std::move(b)}; // does not use initializer list
>>>>> constructor, calls move constructor
>>>>> std::vector<std::function<void ()>> e{}; // default constructor
>>>>> std::vector<std::function<void ()>> f{std::move(e)}; // expect same
>>>>> behavior as d
>>>>>
>>>>> Currently the last line does not compile because it tries to use the
>>>>> initializer_list constructor.
>>>>>
>>>>> What I want is that first the compiler tries all non-initializer_list
>>>>> constructors, and that it only uses the initializer_list one if none of
>>>>> those work.
>>>>>
>>>>> Currently you can't use uniform initialization in generic code,
>>>>> because it can break where initialization with parenthesis wouldn't break
>>>>> if someone uses your code with an object with an initializer list
>>>>> constructor. Which is a shame. Uniform initialization would be great for
>>>>> generic code.
>>>>>
>>>>> Cheers,
>>>>>
>>>>> Malte
>>>>>
>>>>
>>>> Ignoring the fact that this is a *major* breaking change and therefore
>>>> a non-starter, it also doesn't really solve the problem.
>>>>
>>>> Let's say I have a vector<vector<int>>. What should this do?
>>>>
>>>> vector<vector<int>> t = {{20}};
>>>>
>>>> It could be use an initializer_list for both, thus creating a
>>>> one-element vector that contains a one-element vector<int>. Or it could use
>>>> initializer_list for the outer one and constructor initialization for the
>>>> inner one, thus creating a one-element vector that contains a 20 element
>>>> vector<int>. Your way would pick #2. Is there a way to make it pick #1?
>>>>
>>>> vector<vector<int>> t = {{{{20}}}};
>>>>
>>>> Would this force it to use initializer list construction for both? If
>>>> so, it's a bit odd for doing that, with all of those {} pairs.
>>>>
>>>> The core of the problem is that uniform initialization is grammatically
>>>> tied to something else: construction via initializer_list. If there's a
>>>> conflict, only one of them can win. And that's the problem: no matter which
>>>> one we pick, *someone* will want the other one in some situation. Both
>>>> choices are legitimate, for different reasons, at different times, and
>>>> either choice will shadow someone's alternatives, thus forcing them to use
>>>> parenthesis.
>>>>
>>>> It's easy to say that in "generic code", you might want to prefer
>>>> regular constructors over initializer_lists. But what if that's what you
>>>> really wanted? You could very well have a function that takes an arbitrary
>>>> number of values, all of the same type, and you want to shove them into a
>>>> vector or some other container. You shouldn't have to limit yourself to a
>>>> compile-time container like tuple.
>>>>
>>>> At which point you have to stop using uniform initialization.
>>>>
>>>> The problem with your solution (again, besides the fact that it's a
>>>> major breaking change and therefore a non-starter) is that you can reach
>>>> ambiguous constructs
>>>>
>>>> The more I think about it, the more it's clear to me now that we need a
>>>> *language*-level solution for this. We need some way to say that a *
>>>> particular* braced-init-list should ignore initializer_list
>>>> constructors. That way, it's very clear what we're talking about.
>>>>
>>>> I have absolutely no idea what that grammar would look like. It would
>>>> have to be a token sequence that is illegal currently. I was thinking
>>>> something like this:
>>>>
>>>> vector<vector<int>> t = {{. 20}};
>>>>
>>>> The `{.` token sequence represents a construction-braced-init-list.
>>>> This works exactly like a braced-init-list, except that
>>>> non-initializer_list constructors take priority over initializer_list
>>>> constructors.
>>>>
>>>> Now, it's completely obvious that this particular token sequence is
>>>> terribly broken. Consider `{.20}`; Is that a regular braced-init-list with
>>>> one element that is a double-precision 0.20? Or is that a
>>>> construction-braced-init-list with one element that is the integer 20? We
>>>> obviously could pick one over the other, but we don't want to break
>>>> people's code. Code in C++11 that used `{.20}` should still work.
>>>>
>>>> No, `{.` is just an example. We would need something else. Perhaps
>>>> `{^`; I can't see that being particularly legal syntax.
>>>> --
>>>>
>>>>
>>>>
>>>>
>>>
>>> --
>>
>>
>>
>>
>
>
--
------=_Part_171_15029111.1356886266628
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<br><br>On Sunday, December 30, 2012 3:49:52 AM UTC-8, Malte Skarupke wrote=
:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div>It actually seems like m=
y example from above should compile:<br></div><div><br>vector<function&l=
t;void ()>> e{}; // default constructor<br>vector<function<void=
()>> f{move(e)}; // doesn't compile</div>
<div><br></div><div>Currently it does not compile in either GCC or Clang, b=
ut it seems to compile starting at GCC 4.8 and Clang 3.3. I thought that th=
e standard made this impossible by saying that initializer_list constructor=
s should be considered first, and as far as the function declarations are c=
oncerned, you can convert a vector to a function<void ()>.</div></blo=
ckquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div>Only if you actua=
lly compile the function will you notice that a vector doesn't match, at wh=
ich point it's too late to try other overloads.</div>
<div><br></div><div>Since this will apparently start to compile just fine i=
n newer versions of the compilers, that actually makes this less of a probl=
em than I thought. I would be interested though in how they fixed it. If it=
was a fix in the library by doing SFINAE on std::function, then this probl=
em will just re-occur for other types.</div>
<div><br></div><div>In any case I don't think that we need breaking changes=
any more.</div><div><br></div><div>I am still not a big fan of allowing a =
new syntax. Then you would introduce the problem that your templated code w=
ould have to be used differently depending on which constructor syntax you =
use. If I use {} then the user would have to do different behavior than if =
I use {.}</div></blockquote><div><br>What user will need to "do different b=
ehavior?" I don't understand your concern.<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> (or whatever it would end up to be). And =
it's not really realistic to expect the user to know which syntax you use s=
omewhere internally.</div></blockquote><div><br>The user <i>should not care=
</i> what you use internally. They should develop their classes according t=
o whatever concept your code requires (just like in runtime-polymorphism, t=
hey implement classes based on a prototype. The base class). Your template =
code, in turn, should be developed according to the same concept.<br><br>If=
you are implementing a template that takes a type T which shall be CopyCon=
structable, then this expression:<br><br>T t{T{}};<br><br>may violate the c=
oncept constraint. However, this expression, under the rules I propose,:<br=
><br>T t{^ T{}};<br><br>will not violate the concept constraint because it =
will check non-initializer_list constructors first. If your conceptual cons=
traint on T includes an initializer_list<int> constructor, then you s=
hould expect this:<br><br>T t{10};<br><br>to invoke the initializer_list<=
;int> constructor. Similarly, if the concept constraint says that T has =
an initializer_list<T::value_type> constructor, then you should expec=
t this to call that constructor:<br><br>T t{T::value_type(...)};<br><br>It =
will call the initializer_list constructor even if T has a T(T::value_type)=
constructor.<br><br>It's all about matching expectations. Your template co=
de expects certain things from user code. Therefore, user code should confo=
rm to them. As long as both sides understand what the rules are, everything=
should be fine.<br><br></div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">=
<div>(for example try to find out if vector<T>::emplace_back uses () =
or {}. It is hidden pretty well)</div></blockquote><div><br>That makes abso=
lutely no sense. {} is for <i>initialization</i>. `emplace_back` is a <i>fu=
nction call</i>. You would never use it there. You could use it for one of =
the function's <i>arguments</i>, (though it'll be interpreted as an initial=
izer_list, since it's piped through a template parameter) but that's differ=
ent from using it for the function itself. Which you can't do.<br><br>The w=
hole point of uniform initialization is that it's <i>initialization.</i><br=
> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div>Which is by the way another reason to never use {} syntax in templated=
code. Even if it is unambiguous it will probably be unexpected.</div></blo=
ckquote><div><br>Unexpected by whom?<br> </div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div><br></div><div>Malte</div><br><div class=3D"gmai=
l_quote">2012/12/30 Nicol Bolas <span dir=3D"ltr"><<a href=3D"javascript=
:" target=3D"_blank" gdf-obfuscated-mailto=3D"X_ZvTbJJv2cJ">jmck...@gmail.c=
om</a>></span><br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div><br><br>On Saturday, December 29, 2012 =
3:55:41 PM UTC-8, Malte Skarupke wrote:<blockquote class=3D"gmail_quote" st=
yle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1=
ex">
<div>Both syntaxes would actually be unambiguous. The current one is and th=
e changed one would be.<br></div><div>The case you mentioned would be like =
this:</div><div>vector<vector<int>> a{{20}}; // the vector<i=
nt> contains 20 elements</div>
<div>vector<vector<int>> a{{{20}}}; // the vector<int> co=
ntains one element</div><div><br></div><div>Currently the vector<int>=
contains one element in both cases, and there is no way to make it contain=
20 elements using uniform initialization.</div>
<div><br></div><div>I was reading through some old standardization document=
s because I wanted to figure out why the current behavior for the construct=
or order was chosen. (I couldn't find it. Too many texts...) And it is just=
disheartening to see that the whole reason why this was done was to find o=
ne uniform initialization that could be used everywhere. And then that does=
n't work for templated code.</div>
</blockquote></div><div><br>In what way? It does exactly what it says it do=
es in templated code.<br> </div><div><blockquote class=3D"gmail_quote"=
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-lef=
t:1ex">
<div>At this point you have to tell people to never use uniform initializat=
ion in templated code. Because if you use parenthesis and the code doesn't =
compile, the user can fix it by adding the required constructors to her cla=
ss. If you use curly braces and the code doesn't compile, the user can only=
fix it by removing the initializer_list constructor from her class.</div>
</blockquote></div><div><br>... what? The problem isn't that code doesn't c=
ompile; indeed, the problem is that it <i>does</i> compile. The problem is =
that doesn't necessarily do what you wanted if what you wanted was to call =
a non-initializer_list constructor <i>and</i> the braced-init-list you prov=
ide matches an initializer_list constructor.<br>
<br></div><div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l=
eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
<div>The latter is clearly the worse solution and often impossible, (how do=
you remove the initializer_list constructor from vector<function<voi=
d ()>>?) so the recommendation is logically to not use uniform initia=
lization in templated code.</div>
</blockquote></div><div><br>The initializer_list constructors of `vector<=
;function<void()>>` do not interfere with calling constructors in =
any way. This is completely unambiguous:<br><br>vector<function<void(=
)>> v =3D {20};<br>
<br>You're making a vector with 20 default-constructed entries. This <i>can=
not</i> call the initializer_list constructor, because `{20}` cannot be con=
verted into an `initializer_list<function<<wbr>void()>>`. The i=
nitializer_list constructor does not interfere in any way, shape, or form.<=
br>
<br>This is also completely unambiguous:<br><br>vector<function<void(=
)>> v =3D {{SomeVoidFunc}, {OtherVoidFunc}};<br><br>This uses the ini=
tializer_list constructor to construct a vector of 2 functions.<br><br>The =
only problem with `vector`'s constructors and uniform initialization is if =
you use `vector<int>` or similar types:<br>
<br>vector<int> =3D {20};<br><br>This is ambiguous <i>only</i> becaus=
e the initializer_list constructor for vector<int> is of type `initia=
lizer_list<int>`, which is what `{20}` resolves to. This interferes w=
ith the regular constructor of `vector` that takes a `size_t`, thus masking=
the use of that constructor.<br>
<br>I think you're not fully understanding the problem. It is a non-trivial=
problem, but it isn't as dire as you suggest.<br> </div><div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1=
px #ccc solid;padding-left:1ex">
<div>I think if we want to be able to write generic code that is able to sa=
y "just instantiate that object with the arguments given by the user" there=
are two solutions:</div><div>a) break some code by changing the order in w=
hich initializer_list and other constructors are considered. (my proposal)<=
/div>
<div>b) Another new constructor syntax. (your proposal)</div></blockquote><=
/div><div><br>It's not a "new constructor syntax". It's the <i>same</i> con=
structor syntax with slightly modified rules. It behaves identically except=
in which constructors it prefers.<br>
</div><div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin=
-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div>Honestly betw=
een these two options this is probably not going to go anywhere, and it is =
truly a shame.</div>
</blockquote></div><div><br>Well nothing is going to come of it if you don'=
t believe it's going to.<br><br>a) is not happening. In order for you to co=
nvince the committee to make such a major backwards-incompatible change, yo=
u would need to provide serious evidence from many actual, live C++11 proje=
cts that it would be non-disruptive to them.<br>
<br>b) is much more reasonable. It's far less intrusive overall. It will ca=
use zero backwards incompatible changes. And so forth. And it's really easy=
to specify in the standard. The only real problem is convincing people tha=
t it's an important enough issue to fix, and finding the right syntax for i=
t.<br>
<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0=
..8ex;border-left:1px #ccc solid;padding-left:1ex"><div>2012/12/29 Nicol Bol=
as <span dir=3D"ltr"><<a>jmck...@gmail.com</a>></span><div><div>
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div><br><br>On Saturday, December 29, 2012 =
9:36:46 AM UTC-8, <a>maltes...@gmail.com</a> wrote:<blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex">
I would like to see this behavior:<br><br>std::vector<int> a{10}; // =
does not use initializer list constructor. creates a vector with ten elemen=
ts<br>std::vector<int> b{10, 20, 30}; // calls initializer list const=
ructor<br>
std::vector<int> c{{10}}; // calls initializer list constructor, crea=
tes vector with the element 10<br>std::vector<int> d{std::move(b)}; /=
/ does not use initializer list constructor, calls move constructor<br>
std::vector<std::function<void ()>> e{}; // default constructor=
<br>std::vector<std::function<void ()>> f{std::move(e)}; // exp=
ect same behavior as d<br><br>Currently the last line does not compile beca=
use it tries to use the initializer_list constructor.<br>
<br>What I want is that first the compiler tries all non-initializer_list c=
onstructors, and that it only uses the initializer_list one if none of thos=
e work.<br><br>Currently you can't use uniform initialization in generic co=
de, because it can break where initialization with parenthesis wouldn't bre=
ak if someone uses your code with an object with an initializer list constr=
uctor. Which is a shame. Uniform initialization would be great for generic =
code.<br>
<br>Cheers,<br><br>Malte<br></blockquote></div><div><br>Ignoring the fact t=
hat this is a <i>major</i> breaking change and therefore a non-starter, it =
also doesn't really solve the problem.<br><br>Let's say I have a vector<=
vector<int>>. What should this do?<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>vector</span><span style=3D"color:#660"><</span><span>vector</spa=
n><span style=3D"color:#080"><int></span><span style=3D"color:#660">&=
gt;</span><span> t </span><span style=3D"color:#660">=3D</span><span> </spa=
n><span style=3D"color:#660">{{</span><span style=3D"color:#066">20</span><=
span style=3D"color:#660">}};</span><span><br>
</span></div></code></div><br>It could be use an initializer_list for both,=
thus creating a one-element vector that contains a one-element vector<i=
nt>. Or it could use initializer_list for the outer one and constructor =
initialization for the inner one, thus creating a one-element vector that c=
ontains a 20 element vector<int>. Your way would pick #2. Is there a =
way to make it pick #1?<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>vector</span><span style=3D"color:#660"><</span><span>vector</spa=
n><span style=3D"color:#080"><int></span><span style=3D"color:#660">&=
gt;</span><span> t </span><span style=3D"color:#660">=3D</span><span> </spa=
n><span style=3D"color:#660">{{{{</span><span style=3D"color:#066">20</span=
><span style=3D"color:#660">}}}};</span><span><br>
</span></div></code></div><br>Would this force it to use initializer list c=
onstruction for both? If so, it's a bit odd for doing that, with all of tho=
se {} pairs.<br><br>The core of the problem is that uniform initialization =
is grammatically tied to something else: construction via initializer_list.=
If there's a conflict, only one of them can win. And that's the problem: n=
o matter which one we pick, <i>someone</i> will want the other one in some =
situation. Both choices are legitimate, for different reasons, at different=
times, and either choice will shadow someone's alternatives, thus forcing =
them to use parenthesis.<br>
<br>It's easy to say that in "generic code", you might want to prefer regul=
ar constructors over initializer_lists. But what if that's what you really =
wanted? You could very well have a function that takes an arbitrary number =
of values, all of the same type, and you want to shove them into a vector o=
r some other container. You shouldn't have to limit yourself to a compile-t=
ime container like tuple.<br>
<br> At which point you have to stop using uniform initialization.</di=
v><br>The problem with your solution (again, besides the fact that it's a m=
ajor breaking change and therefore a non-starter) is that you can reach amb=
iguous constructs<br>
<br>The more I think about it, the more it's clear to me now that we need a=
<i>language</i>-level solution for this. We need some way to say that a <i=
>particular</i> braced-init-list should ignore initializer_list constructor=
s. That way, it's very clear what we're talking about.<br>
<br>I have absolutely no idea what that grammar would look like. It would h=
ave to be a token sequence that is illegal currently. I was thinking someth=
ing like this:<br><br><div style=3D"background-color:rgb(250,250,250);borde=
r-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:brea=
k-word">
<code><div><span>vector</span><span style=3D"color:#660"><</span><span>v=
ector</span><span style=3D"color:#080"><int></span><span style=3D"col=
or:#660">></span><span> t </span><span style=3D"color:#660">=3D</span><s=
pan> </span><span style=3D"color:#660">{{.</span><span> </span><span style=
=3D"color:#066">20</span><span style=3D"color:#660">}};</span><span><br>
</span></div></code></div><br>The `{.` token sequence represents a construc=
tion-braced-init-list. This works exactly like a braced-init-list, except t=
hat non-initializer_list constructors take priority over initializer_list c=
onstructors.<br>
<br>Now, it's completely obvious that this particular token sequence is ter=
ribly broken. Consider `{.20}`; Is that a regular braced-init-list with one=
element that is a double-precision 0.20? Or is that a construction-braced-=
init-list with one element that is the integer 20? We obviously could pick =
one over the other, but we don't want to break people's code. Code in C++11=
that used `{.20}` should still work.<br>
<br>No, `{.` is just an example. We would need something else. Perhaps `{^`=
; I can't see that being particularly legal syntax.<span><font color=3D"#88=
8888"><br>
-- <br>
<br>
<br>
<br>
</font></span></blockquote></div></div></div><br>
</blockquote>
-- <br>
<br>
<br>
<br>
</blockquote></div><br>
</blockquote>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_171_15029111.1356886266628--
.
Author: Malte Skarupke <malteskarupke@gmail.com>
Date: Sun, 30 Dec 2012 19:26:23 +0100
Raw View
--f46d04389415de5c6a04d21609fd
Content-Type: text/plain; charset=ISO-8859-1
What I meant with that is for example this:
vector<vector<int>> a;
a.emplace_back(10);
We know that this emplaces a vector with ten zeros. How do we know that?
Somewhere inside of emplace_back there is a call to construct() which looks
something like this:
template<typename T, typename... A>
void construct(T * ptr, A &&... arg)
{
new (ptr) T(forward<A>(arg)...);
}
But what if construct looked like this?
template<typename T, typename... A>
void construct(T * ptr, A &&... arg)
{
new (ptr) T{forward<A>(arg)...};
}
Now the same code would create a vector that has one element: the number 10.
So for the client to be able to use emplace_back correctly, the client has
to know that it will use () and not {} (or in this case it has to know that
emplace_back uses construct which uses () and not {}). And the client
usually expects that. If they wanted to use the initializer list
constructor, they would just do it like this:
a.emplace_back({10});
Because of this you should never initialize using uniform initialization in
templated code. If you did, then the client wouldn't be able to call some
constructors any more.
It sounds like using {^} would behave mostly like () except that it would
also work for arrays and structs without declared constructors. That's
cool, but then the client has to know which of the three initializations is
used in templated code. Currently you can always expect initialization
using (). Do we want to make that more complicated? It might be worth it,
but only if we could guarantee that you can really use {^} for EVERYTHING.
Malte
2012/12/30 Nicol Bolas <jmckesson@gmail.com>
>
>
> On Sunday, December 30, 2012 3:49:52 AM UTC-8, Malte Skarupke wrote:
>>
>> It actually seems like my example from above should compile:
>>
>> vector<function<void ()>> e{}; // default constructor
>> vector<function<void ()>> f{move(e)}; // doesn't compile
>>
>> Currently it does not compile in either GCC or Clang, but it seems to
>> compile starting at GCC 4.8 and Clang 3.3. I thought that the standard made
>> this impossible by saying that initializer_list constructors should be
>> considered first, and as far as the function declarations are concerned,
>> you can convert a vector to a function<void ()>.
>>
> Only if you actually compile the function will you notice that a vector
>> doesn't match, at which point it's too late to try other overloads.
>>
>> Since this will apparently start to compile just fine in newer versions
>> of the compilers, that actually makes this less of a problem than I
>> thought. I would be interested though in how they fixed it. If it was a fix
>> in the library by doing SFINAE on std::function, then this problem will
>> just re-occur for other types.
>>
>> In any case I don't think that we need breaking changes any more.
>>
>> I am still not a big fan of allowing a new syntax. Then you would
>> introduce the problem that your templated code would have to be used
>> differently depending on which constructor syntax you use. If I use {} then
>> the user would have to do different behavior than if I use {.}
>>
>
> What user will need to "do different behavior?" I don't understand your
> concern.
>
>
>> (or whatever it would end up to be). And it's not really realistic to
>> expect the user to know which syntax you use somewhere internally.
>>
>
> The user *should not care* what you use internally. They should develop
> their classes according to whatever concept your code requires (just like
> in runtime-polymorphism, they implement classes based on a prototype. The
> base class). Your template code, in turn, should be developed according to
> the same concept.
>
> If you are implementing a template that takes a type T which shall be
> CopyConstructable, then this expression:
>
> T t{T{}};
>
> may violate the concept constraint. However, this expression, under the
> rules I propose,:
>
> T t{^ T{}};
>
> will not violate the concept constraint because it will check
> non-initializer_list constructors first. If your conceptual constraint on T
> includes an initializer_list<int> constructor, then you should expect this:
>
> T t{10};
>
> to invoke the initializer_list<int> constructor. Similarly, if the concept
> constraint says that T has an initializer_list<T::value_type> constructor,
> then you should expect this to call that constructor:
>
> T t{T::value_type(...)};
>
> It will call the initializer_list constructor even if T has a
> T(T::value_type) constructor.
>
> It's all about matching expectations. Your template code expects certain
> things from user code. Therefore, user code should conform to them. As long
> as both sides understand what the rules are, everything should be fine.
>
> (for example try to find out if vector<T>::emplace_back uses () or {}. It
>> is hidden pretty well)
>>
>
> That makes absolutely no sense. {} is for *initialization*.
> `emplace_back` is a *function call*. You would never use it there. You
> could use it for one of the function's *arguments*, (though it'll be
> interpreted as an initializer_list, since it's piped through a template
> parameter) but that's different from using it for the function itself.
> Which you can't do.
>
> The whole point of uniform initialization is that it's *initialization.*
>
>
>> Which is by the way another reason to never use {} syntax in templated
>> code. Even if it is unambiguous it will probably be unexpected.
>>
>
> Unexpected by whom?
>
>
>>
>> Malte
>>
>> 2012/12/30 Nicol Bolas <jmck...@gmail.com>
>>
>>
>>>
>>> On Saturday, December 29, 2012 3:55:41 PM UTC-8, Malte Skarupke wrote:
>>>>
>>>> Both syntaxes would actually be unambiguous. The current one is and the
>>>> changed one would be.
>>>> The case you mentioned would be like this:
>>>> vector<vector<int>> a{{20}}; // the vector<int> contains 20 elements
>>>> vector<vector<int>> a{{{20}}}; // the vector<int> contains one element
>>>>
>>>> Currently the vector<int> contains one element in both cases, and there
>>>> is no way to make it contain 20 elements using uniform initialization.
>>>>
>>>> I was reading through some old standardization documents because I
>>>> wanted to figure out why the current behavior for the constructor order was
>>>> chosen. (I couldn't find it. Too many texts...) And it is just
>>>> disheartening to see that the whole reason why this was done was to find
>>>> one uniform initialization that could be used everywhere. And then that
>>>> doesn't work for templated code.
>>>>
>>>
>>> In what way? It does exactly what it says it does in templated code.
>>>
>>>
>>>> At this point you have to tell people to never use uniform
>>>> initialization in templated code. Because if you use parenthesis and the
>>>> code doesn't compile, the user can fix it by adding the required
>>>> constructors to her class. If you use curly braces and the code doesn't
>>>> compile, the user can only fix it by removing the initializer_list
>>>> constructor from her class.
>>>>
>>>
>>> ... what? The problem isn't that code doesn't compile; indeed, the
>>> problem is that it *does* compile. The problem is that doesn't
>>> necessarily do what you wanted if what you wanted was to call a
>>> non-initializer_list constructor *and* the braced-init-list you provide
>>> matches an initializer_list constructor.
>>>
>>> The latter is clearly the worse solution and often impossible, (how do
>>>> you remove the initializer_list constructor from vector<function<void
>>>> ()>>?) so the recommendation is logically to not use uniform initialization
>>>> in templated code.
>>>>
>>>
>>> The initializer_list constructors of `vector<function<void()>>` do not
>>> interfere with calling constructors in any way. This is completely
>>> unambiguous:
>>>
>>> vector<function<void()>> v = {20};
>>>
>>> You're making a vector with 20 default-constructed entries. This *cannot
>>> * call the initializer_list constructor, because `{20}` cannot be
>>> converted into an `initializer_list<function<void()>>`. The
>>> initializer_list constructor does not interfere in any way, shape, or form.
>>>
>>> This is also completely unambiguous:
>>>
>>> vector<function<void()>> v = {{SomeVoidFunc}, {OtherVoidFunc}};
>>>
>>> This uses the initializer_list constructor to construct a vector of 2
>>> functions.
>>>
>>> The only problem with `vector`'s constructors and uniform initialization
>>> is if you use `vector<int>` or similar types:
>>>
>>> vector<int> = {20};
>>>
>>> This is ambiguous *only* because the initializer_list constructor for
>>> vector<int> is of type `initializer_list<int>`, which is what `{20}`
>>> resolves to. This interferes with the regular constructor of `vector` that
>>> takes a `size_t`, thus masking the use of that constructor.
>>>
>>> I think you're not fully understanding the problem. It is a non-trivial
>>> problem, but it isn't as dire as you suggest.
>>>
>>>
>>>> I think if we want to be able to write generic code that is able to say
>>>> "just instantiate that object with the arguments given by the user" there
>>>> are two solutions:
>>>> a) break some code by changing the order in which initializer_list and
>>>> other constructors are considered. (my proposal)
>>>> b) Another new constructor syntax. (your proposal)
>>>>
>>>
>>> It's not a "new constructor syntax". It's the *same* constructor syntax
>>> with slightly modified rules. It behaves identically except in which
>>> constructors it prefers.
>>>
>>>
>>>> Honestly between these two options this is probably not going to go
>>>> anywhere, and it is truly a shame.
>>>>
>>>
>>> Well nothing is going to come of it if you don't believe it's going to.
>>>
>>> a) is not happening. In order for you to convince the committee to make
>>> such a major backwards-incompatible change, you would need to provide
>>> serious evidence from many actual, live C++11 projects that it would be
>>> non-disruptive to them.
>>>
>>> b) is much more reasonable. It's far less intrusive overall. It will
>>> cause zero backwards incompatible changes. And so forth. And it's really
>>> easy to specify in the standard. The only real problem is convincing people
>>> that it's an important enough issue to fix, and finding the right syntax
>>> for it.
>>>
>>> 2012/12/29 Nicol Bolas <jmck...@gmail.com>
>>>>
>>>>
>>>>>
>>>>> On Saturday, December 29, 2012 9:36:46 AM UTC-8, maltes...@gmail.comwrote:
>>>>>>
>>>>>> I would like to see this behavior:
>>>>>>
>>>>>> std::vector<int> a{10}; // does not use initializer list constructor.
>>>>>> creates a vector with ten elements
>>>>>> std::vector<int> b{10, 20, 30}; // calls initializer list constructor
>>>>>> std::vector<int> c{{10}}; // calls initializer list constructor,
>>>>>> creates vector with the element 10
>>>>>> std::vector<int> d{std::move(b)}; // does not use initializer list
>>>>>> constructor, calls move constructor
>>>>>> std::vector<std::function<void ()>> e{}; // default constructor
>>>>>> std::vector<std::function<void ()>> f{std::move(e)}; // expect same
>>>>>> behavior as d
>>>>>>
>>>>>> Currently the last line does not compile because it tries to use the
>>>>>> initializer_list constructor.
>>>>>>
>>>>>> What I want is that first the compiler tries all non-initializer_list
>>>>>> constructors, and that it only uses the initializer_list one if none of
>>>>>> those work.
>>>>>>
>>>>>> Currently you can't use uniform initialization in generic code,
>>>>>> because it can break where initialization with parenthesis wouldn't break
>>>>>> if someone uses your code with an object with an initializer list
>>>>>> constructor. Which is a shame. Uniform initialization would be great for
>>>>>> generic code.
>>>>>>
>>>>>> Cheers,
>>>>>>
>>>>>> Malte
>>>>>>
>>>>>
>>>>> Ignoring the fact that this is a *major* breaking change and
>>>>> therefore a non-starter, it also doesn't really solve the problem.
>>>>>
>>>>> Let's say I have a vector<vector<int>>. What should this do?
>>>>>
>>>>> vector<vector<int>> t = {{20}};
>>>>>
>>>>> It could be use an initializer_list for both, thus creating a
>>>>> one-element vector that contains a one-element vector<int>. Or it could use
>>>>> initializer_list for the outer one and constructor initialization for the
>>>>> inner one, thus creating a one-element vector that contains a 20 element
>>>>> vector<int>. Your way would pick #2. Is there a way to make it pick #1?
>>>>>
>>>>> vector<vector<int>> t = {{{{20}}}};
>>>>>
>>>>> Would this force it to use initializer list construction for both? If
>>>>> so, it's a bit odd for doing that, with all of those {} pairs.
>>>>>
>>>>> The core of the problem is that uniform initialization is
>>>>> grammatically tied to something else: construction via initializer_list. If
>>>>> there's a conflict, only one of them can win. And that's the problem: no
>>>>> matter which one we pick, *someone* will want the other one in some
>>>>> situation. Both choices are legitimate, for different reasons, at different
>>>>> times, and either choice will shadow someone's alternatives, thus forcing
>>>>> them to use parenthesis.
>>>>>
>>>>> It's easy to say that in "generic code", you might want to prefer
>>>>> regular constructors over initializer_lists. But what if that's what you
>>>>> really wanted? You could very well have a function that takes an arbitrary
>>>>> number of values, all of the same type, and you want to shove them into a
>>>>> vector or some other container. You shouldn't have to limit yourself to a
>>>>> compile-time container like tuple.
>>>>>
>>>>> At which point you have to stop using uniform initialization.
>>>>>
>>>>> The problem with your solution (again, besides the fact that it's a
>>>>> major breaking change and therefore a non-starter) is that you can reach
>>>>> ambiguous constructs
>>>>>
>>>>> The more I think about it, the more it's clear to me now that we need
>>>>> a *language*-level solution for this. We need some way to say that a *
>>>>> particular* braced-init-list should ignore initializer_list
>>>>> constructors. That way, it's very clear what we're talking about.
>>>>>
>>>>> I have absolutely no idea what that grammar would look like. It would
>>>>> have to be a token sequence that is illegal currently. I was thinking
>>>>> something like this:
>>>>>
>>>>> vector<vector<int>> t = {{. 20}};
>>>>>
>>>>> The `{.` token sequence represents a construction-braced-init-list.
>>>>> This works exactly like a braced-init-list, except that
>>>>> non-initializer_list constructors take priority over initializer_list
>>>>> constructors.
>>>>>
>>>>> Now, it's completely obvious that this particular token sequence is
>>>>> terribly broken. Consider `{.20}`; Is that a regular braced-init-list with
>>>>> one element that is a double-precision 0.20? Or is that a
>>>>> construction-braced-init-list with one element that is the integer 20? We
>>>>> obviously could pick one over the other, but we don't want to break
>>>>> people's code. Code in C++11 that used `{.20}` should still work.
>>>>>
>>>>> No, `{.` is just an example. We would need something else. Perhaps
>>>>> `{^`; I can't see that being particularly legal syntax.
>>>>> --
>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>>> --
>>>
>>>
>>>
>>>
>>
>> --
>
>
>
>
--
--f46d04389415de5c6a04d21609fd
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div>What I meant with that is for example this:<br></div><div>vector<ve=
ctor<int>> a;</div><div>a.emplace_back(10);</div><div><br></div><d=
iv>We know that this emplaces a vector with ten zeros. How do we know that?=
Somewhere inside of emplace_back there is a call to construct() which look=
s something like this:</div>
<div>template<typename T, typename... A></div><div>void construct(T *=
ptr, A &&... arg)</div><div>{</div><div>=A0 =A0 new (ptr) T(forwar=
d<A>(arg)...);</div><div>}</div><div><br></div><div>But what if const=
ruct looked like this?</div>
<div><br></div>
<div>template<typename T, typename... A></div><div>void construct(T *=
ptr, A &&... arg)</div><div>{</div><div>=A0 =A0 new (ptr) T{forwar=
d<A>(arg)...};</div><div>}</div><div><br></div><div>Now the same code=
would create a vector that has one element: the number 10.</div>
<div><br></div><div>So for the client to be able to use emplace_back correc=
tly, the client has to know that it will use () and not {} (or in this case=
it has to know that emplace_back uses construct which uses () and not {}).=
And the client usually expects that. If they wanted to use the initializer=
list constructor, they would just do it like this:</div>
<div>a.emplace_back({10});</div><div><br></div><div>Because of this you sho=
uld never initialize using uniform initialization in templated code. If you=
did, then the client wouldn't be able to call some constructors any mo=
re.</div>
<div>It sounds like using {^} would behave mostly like () except that it wo=
uld also work for arrays and structs without declared constructors. That=
9;s cool, but then the client has to know which of the three initialization=
s is used in templated code. Currently you can always expect initialization=
using (). Do we want to make that more complicated? It might be worth it, =
but only if we could guarantee that you can really use {^} for EVERYTHING.<=
/div>
<div><br></div><div>Malte</div><br><div class=3D"gmail_quote">2012/12/30 Ni=
col Bolas <span dir=3D"ltr"><<a href=3D"mailto:jmckesson@gmail.com" targ=
et=3D"_blank">jmckesson@gmail.com</a>></span><br><blockquote class=3D"gm=
ail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-le=
ft:1ex">
<div class=3D"im"><br><br>On Sunday, December 30, 2012 3:49:52 AM UTC-8, Ma=
lte Skarupke wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;marg=
in-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div>It actually=
seems like my example from above should compile:<br>
</div><div><br>vector<function<void ()>> e{}; // default constr=
uctor<br>vector<function<void ()>> f{move(e)}; // doesn't c=
ompile</div>
<div><br></div><div>Currently it does not compile in either GCC or Clang, b=
ut it seems to compile starting at GCC 4.8 and Clang 3.3. I thought that th=
e standard made this impossible by saying that initializer_list constructor=
s should be considered first, and as far as the function declarations are c=
oncerned, you can convert a vector to a function<void ()>.</div>
</blockquote><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-lef=
t:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div>Only if you actua=
lly compile the function will you notice that a vector doesn't match, a=
t which point it's too late to try other overloads.</div>
<div><br></div><div>Since this will apparently start to compile just fine i=
n newer versions of the compilers, that actually makes this less of a probl=
em than I thought. I would be interested though in how they fixed it. If it=
was a fix in the library by doing SFINAE on std::function, then this probl=
em will just re-occur for other types.</div>
<div><br></div><div>In any case I don't think that we need breaking cha=
nges any more.</div><div><br></div><div>I am still not a big fan of allowin=
g a new syntax. Then you would introduce the problem that your templated co=
de would have to be used differently depending on which constructor syntax =
you use. If I use {} then the user would have to do different behavior than=
if I use {.}</div>
</blockquote></div><div><br>What user will need to "do different behav=
ior?" I don't understand your concern.<br>=A0</div><div class=3D"i=
m"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex">
<div> (or whatever it would end up to be). And it's not really realisti=
c to expect the user to know which syntax you use somewhere internally.</di=
v></blockquote></div><div><br>The user <i>should not care</i> what you use =
internally. They should develop their classes according to whatever concept=
your code requires (just like in runtime-polymorphism, they implement clas=
ses based on a prototype. The base class). Your template code, in turn, sho=
uld be developed according to the same concept.<br>
<br>If you are implementing a template that takes a type T which shall be C=
opyConstructable, then this expression:<br><br>T t{T{}};<br><br>may violate=
the concept constraint. However, this expression, under the rules I propos=
e,:<br>
<br>T t{^ T{}};<br><br>will not violate the concept constraint because it w=
ill check non-initializer_list constructors first. If your conceptual const=
raint on T includes an initializer_list<int> constructor, then you sh=
ould expect this:<br>
<br>T t{10};<br><br>to invoke the initializer_list<int> constructor. =
Similarly, if the concept constraint says that T has an initializer_list<=
;T::value_type> constructor, then you should expect this to call that co=
nstructor:<br>
<br>T t{T::value_type(...)};<br><br>It will call the initializer_list const=
ructor even if T has a T(T::value_type) constructor.<br><br>It's all ab=
out matching expectations. Your template code expects certain things from u=
ser code. Therefore, user code should conform to them. As long as both side=
s understand what the rules are, everything should be fine.<br>
<br></div><div class=3D"im"><blockquote class=3D"gmail_quote" style=3D"marg=
in:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div>(f=
or example try to find out if vector<T>::emplace_back uses () or {}. =
It is hidden pretty well)</div>
</blockquote></div><div><br>That makes absolutely no sense. {} is for <i>in=
itialization</i>. `emplace_back` is a <i>function call</i>. You would never=
use it there. You could use it for one of the function's <i>arguments<=
/i>, (though it'll be interpreted as an initializer_list, since it'=
s piped through a template parameter) but that's different from using i=
t for the function itself. Which you can't do.<br>
<br>The whole point of uniform initialization is that it's <i>initializ=
ation.</i><br>=A0</div><div class=3D"im"><blockquote class=3D"gmail_quote" =
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left=
:1ex">
<div>Which is by the way another reason to never use {} syntax in templated=
code. Even if it is unambiguous it will probably be unexpected.</div></blo=
ckquote></div><div><br>Unexpected by whom?<br>=A0</div><blockquote class=3D=
"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc soli=
d;padding-left:1ex">
<div><br></div><div>Malte</div><br><div class=3D"gmail_quote">2012/12/30 Ni=
col Bolas <span dir=3D"ltr"><<a>jmck...@gmail.com</a>></span><div><di=
v class=3D"h5"><br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div><br><br>On Saturday, December 29, 2012 =
3:55:41 PM UTC-8, Malte Skarupke wrote:<blockquote class=3D"gmail_quote" st=
yle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1=
ex">
<div>Both syntaxes would actually be unambiguous. The current one is and th=
e changed one would be.<br></div><div>The case you mentioned would be like =
this:</div><div>vector<vector<int>> a{{20}}; // the vector<i=
nt> contains 20 elements</div>
<div>vector<vector<int>> a{{{20}}}; // the vector<int> co=
ntains one element</div><div><br></div><div>Currently the vector<int>=
contains one element in both cases, and there is no way to make it contain=
20 elements using uniform initialization.</div>
<div><br></div><div>I was reading through some old standardization document=
s because I wanted to figure out why the current behavior for the construct=
or order was chosen. (I couldn't find it. Too many texts...) And it is =
just disheartening to see that the whole reason why this was done was to fi=
nd one uniform initialization that could be used everywhere. And then that =
doesn't work for templated code.</div>
</blockquote></div><div><br>In what way? It does exactly what it says it do=
es in templated code.<br>=A0</div><div><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1=
ex">
<div>At this point you have to tell people to never use uniform initializat=
ion in templated code. Because if you use parenthesis and the code doesn=
9;t compile, the user can fix it by adding the required constructors to her=
class. If you use curly braces and the code doesn't compile, the user =
can only fix it by removing the initializer_list constructor from her class=
..</div>
</blockquote></div><div><br>... what? The problem isn't that code doesn=
't compile; indeed, the problem is that it <i>does</i> compile. The pro=
blem is that doesn't necessarily do what you wanted if what you wanted =
was to call a non-initializer_list constructor <i>and</i> the braced-init-l=
ist you provide matches an initializer_list constructor.<br>
<br></div><div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l=
eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
<div>The latter is clearly the worse solution and often impossible, (how do=
you remove the initializer_list constructor from vector<function<voi=
d ()>>?) so the recommendation is logically to not use uniform initia=
lization in templated code.</div>
</blockquote></div><div><br>The initializer_list constructors of `vector<=
;function<void()>>` do not interfere with calling constructors in =
any way. This is completely unambiguous:<br><br>vector<function<void(=
)>> v =3D {20};<br>
<br>You're making a vector with 20 default-constructed entries. This <i=
>cannot</i> call the initializer_list constructor, because `{20}` cannot be=
converted into an `initializer_list<function<void()>>`. The in=
itializer_list constructor does not interfere in any way, shape, or form.<b=
r>
<br>This is also completely unambiguous:<br><br>vector<function<void(=
)>> v =3D {{SomeVoidFunc}, {OtherVoidFunc}};<br><br>This uses the ini=
tializer_list constructor to construct a vector of 2 functions.<br><br>The =
only problem with `vector`'s constructors and uniform initialization is=
if you use `vector<int>` or similar types:<br>
<br>vector<int> =3D {20};<br><br>This is ambiguous <i>only</i> becaus=
e the initializer_list constructor for vector<int> is of type `initia=
lizer_list<int>`, which is what `{20}` resolves to. This interferes w=
ith the regular constructor of `vector` that takes a `size_t`, thus masking=
the use of that constructor.<br>
<br>I think you're not fully understanding the problem. It is a non-tri=
vial problem, but it isn't as dire as you suggest.<br>=A0</div><div><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-l=
eft:1px #ccc solid;padding-left:1ex">
<div>I think if we want to be able to write generic code that is able to sa=
y "just instantiate that object with the arguments given by the user&q=
uot; there are two solutions:</div><div>a) break some code by changing the =
order in which initializer_list and other constructors are considered. (my =
proposal)</div>
<div>b) Another new constructor syntax. (your proposal)</div></blockquote><=
/div><div><br>It's not a "new constructor syntax". It's t=
he <i>same</i> constructor syntax with slightly modified rules. It behaves =
identically except in which constructors it prefers.<br>
=A0</div><div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-le=
ft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div>Honestly between=
these two options this is probably not going to go anywhere, and it is tru=
ly a shame.</div>
</blockquote></div><div><br>Well nothing is going to come of it if you don&=
#39;t believe it's going to.<br><br>a) is not happening. In order for y=
ou to convince the committee to make such a major backwards-incompatible ch=
ange, you would need to provide serious evidence from many actual, live C++=
11 projects that it would be non-disruptive to them.<br>
<br>b) is much more reasonable. It's far less intrusive overall. It wil=
l cause zero backwards incompatible changes. And so forth. And it's rea=
lly easy to specify in the standard. The only real problem is convincing pe=
ople that it's an important enough issue to fix, and finding the right =
syntax for it.<br>
<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0=
..8ex;border-left:1px #ccc solid;padding-left:1ex"><div>2012/12/29 Nicol Bol=
as <span dir=3D"ltr"><<a>jmck...@gmail.com</a>></span><div><div>
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div><br><br>On Saturday, December 29, 2012 =
9:36:46 AM UTC-8, <a>maltes...@gmail.com</a> wrote:<blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex">
I would like to see this behavior:<br><br>std::vector<int> a{10}; // =
does not use initializer list constructor. creates a vector with ten elemen=
ts<br>std::vector<int> b{10, 20, 30}; // calls initializer list const=
ructor<br>
std::vector<int> c{{10}}; // calls initializer list constructor, crea=
tes vector with the element 10<br>std::vector<int> d{std::move(b)}; /=
/ does not use initializer list constructor, calls move constructor<br>
std::vector<std::function<void ()>> e{}; // default constructor=
<br>std::vector<std::function<void ()>> f{std::move(e)}; // exp=
ect same behavior as d<br><br>Currently the last line does not compile beca=
use it tries to use the initializer_list constructor.<br>
<br>What I want is that first the compiler tries all non-initializer_list c=
onstructors, and that it only uses the initializer_list one if none of thos=
e work.<br><br>Currently you can't use uniform initialization in generi=
c code, because it can break where initialization with parenthesis wouldn&#=
39;t break if someone uses your code with an object with an initializer lis=
t constructor. Which is a shame. Uniform initialization would be great for =
generic code.<br>
<br>Cheers,<br><br>Malte<br></blockquote></div><div><br>Ignoring the fact t=
hat this is a <i>major</i> breaking change and therefore a non-starter, it =
also doesn't really solve the problem.<br><br>Let's say I have a ve=
ctor<vector<int>>. What should this do?<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>vector</span><span style=3D"color:#660"><</span><span>vector</spa=
n><span style=3D"color:#080"><int></span><span style=3D"color:#660">&=
gt;</span><span> t </span><span style=3D"color:#660">=3D</span><span> </spa=
n><span style=3D"color:#660">{{</span><span style=3D"color:#066">20</span><=
span style=3D"color:#660">}};</span><span><br>
</span></div></code></div><br>It could be use an initializer_list for both,=
thus creating a one-element vector that contains a one-element vector<i=
nt>. Or it could use initializer_list for the outer one and constructor =
initialization for the inner one, thus creating a one-element vector that c=
ontains a 20 element vector<int>. Your way would pick #2. Is there a =
way to make it pick #1?<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>vector</span><span style=3D"color:#660"><</span><span>vector</spa=
n><span style=3D"color:#080"><int></span><span style=3D"color:#660">&=
gt;</span><span> t </span><span style=3D"color:#660">=3D</span><span> </spa=
n><span style=3D"color:#660">{{{{</span><span style=3D"color:#066">20</span=
><span style=3D"color:#660">}}}};</span><span><br>
</span></div></code></div><br>Would this force it to use initializer list c=
onstruction for both? If so, it's a bit odd for doing that, with all of=
those {} pairs.<br><br>The core of the problem is that uniform initializat=
ion is grammatically tied to something else: construction via initializer_l=
ist. If there's a conflict, only one of them can win. And that's th=
e problem: no matter which one we pick, <i>someone</i> will want the other =
one in some situation. Both choices are legitimate, for different reasons, =
at different times, and either choice will shadow someone's alternative=
s, thus forcing them to use parenthesis.<br>
<br>It's easy to say that in "generic code", you might want t=
o prefer regular constructors over initializer_lists. But what if that'=
s what you really wanted? You could very well have a function that takes an=
arbitrary number of values, all of the same type, and you want to shove th=
em into a vector or some other container. You shouldn't have to limit y=
ourself to a compile-time container like tuple.<br>
<br>=A0At which point you have to stop using uniform initialization.</div><=
br>The problem with your solution (again, besides the fact that it's a =
major breaking change and therefore a non-starter) is that you can reach am=
biguous constructs<br>
<br>The more I think about it, the more it's clear to me now that we ne=
ed a <i>language</i>-level solution for this. We need some way to say that =
a <i>particular</i> braced-init-list should ignore initializer_list constru=
ctors. That way, it's very clear what we're talking about.<br>
<br>I have absolutely no idea what that grammar would look like. It would h=
ave to be a token sequence that is illegal currently. I was thinking someth=
ing like this:<br><br><div style=3D"background-color:rgb(250,250,250);borde=
r-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:brea=
k-word">
<code><div><span>vector</span><span style=3D"color:#660"><</span><span>v=
ector</span><span style=3D"color:#080"><int></span><span style=3D"col=
or:#660">></span><span> t </span><span style=3D"color:#660">=3D</span><s=
pan> </span><span style=3D"color:#660">{{.</span><span> </span><span style=
=3D"color:#066">20</span><span style=3D"color:#660">}};</span><span><br>
</span></div></code></div><br>The `{.` token sequence represents a construc=
tion-braced-init-list. This works exactly like a braced-init-list, except t=
hat non-initializer_list constructors take priority over initializer_list c=
onstructors.<br>
<br>Now, it's completely obvious that this particular token sequence is=
terribly broken. Consider `{.20}`; Is that a regular braced-init-list with=
one element that is a double-precision 0.20? Or is that a construction-bra=
ced-init-list with one element that is the integer 20? We obviously could p=
ick one over the other, but we don't want to break people's code. C=
ode in C++11 that used `{.20}` should still work.<br>
<br>No, `{.` is just an example. We would need something else. Perhaps `{^`=
; I can't see that being particularly legal syntax.<span><font color=3D=
"#888888"><br>
-- <br>
=A0<br>
=A0<br>
=A0<br>
</font></span></blockquote></div></div></div><br>
</blockquote>
-- <br>
=A0<br>
=A0<br>
=A0<br>
</blockquote></div></div></div><br>
</blockquote>
-- <br>
=A0<br>
=A0<br>
=A0<br>
</blockquote></div><br>
<p></p>
-- <br />
<br />
<br />
<br />
--f46d04389415de5c6a04d21609fd--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 30 Dec 2012 12:50:10 -0800 (PST)
Raw View
------=_Part_196_16526290.1356900610408
Content-Type: text/plain; charset=ISO-8859-1
On Sunday, December 30, 2012 10:26:23 AM UTC-8, Malte Skarupke wrote:
>
> What I meant with that is for example this:
> vector<vector<int>> a;
> a.emplace_back(10);
>
> We know that this emplaces a vector with ten zeros. How do we know that?
> Somewhere inside of emplace_back there is a call to construct() which looks
> something like this:
> template<typename T, typename... A>
> void construct(T * ptr, A &&... arg)
> {
> new (ptr) T(forward<A>(arg)...);
> }
>
> But what if construct looked like this?
>
> template<typename T, typename... A>
> void construct(T * ptr, A &&... arg)
> {
> new (ptr) T{forward<A>(arg)...};
> }
>
> Now the same code would create a vector that has one element: the number
> 10.
>
> So for the client to be able to use emplace_back correctly, the client has
> to know that it will use () and not {} (or in this case it has to know that
> emplace_back uses construct which uses () and not {}). And the client
> usually expects that. If they wanted to use the initializer list
> constructor, they would just do it like this:
> a.emplace_back({10});
>
> Because of this you should never initialize using uniform initialization
> in templated code. If you did, then the client wouldn't be able to call
> some constructors any more.
> It sounds like using {^} would behave mostly like () except that it would
> also work for arrays and structs without declared constructors. That's
> cool, but then the client has to know which of the three initializations is
> used in templated code.
>
Why does the client need to know this? So long as the client provides a
type with the required interface, then it will work. That's the point of
template code; you provide a known interface, and the template uses it.
`construct` doesn't need to care that it actually calls a constructor. You
could easily redefine it to be {^}, and this would allow it to be used on
things that can be uniformly initialized with those parameters. That's a
good thing; it would let you do this:
struct Simple { int foo; int bar;}
std::vector<Simple> v;
v.emplace_back(10, 20);
Just as you could do this:
struct Simple { int foo; int bar;}
Simple s = {10, 20};
This would have been very dangerous for {} syntax, because it would prefer
initializer_list constructors, thus hiding regular ones. But with {^}
syntax, you can get at the constructors.
> Currently you can always expect initialization using ().
>
First, no you can't. People do use uniform initialization, even in template
code.
Second and more importantly, you *shouldn't care*. All you as the client
should care about is providing the interface that the template requires;
it's up to the template writers not to go outside of this interface.
Do we want to make that more complicated?
>
It doesn't make things more complicated; it makes them simpler for the
user. On both ends.
> It might be worth it, but only if we could guarantee that you can really
> use {^} for EVERYTHING.
>
You don't need to. You just need a way to prefer one kind of constructor
over another. The ambiguity will always be there; there simply needs to be
a way to pick one vs. the other.
Right now, we have a method that only calls constructors (ie: ()), and a
method that can call non-constructor things but will prefer
initializer_list constructors if one fits. What we need is third way that
can call non-constructor things but will prefer non-initializer_list
constructors if one fits. Which one that someone wants to use in their
template code is up to them.
And yes, technically, it would allow you to access all of the construction
methods, though obviously you would need more braces:
vector<int> v1{^20};
vector<int> v2{^{^20}};
--
------=_Part_196_16526290.1356900610408
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Sunday, December 30, 2012 10:26:23 AM UTC-8, Malte Skarupke wrote:<block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div>What I meant with that is for e=
xample this:<br></div><div>vector<vector<int>> a;</div><div>a.e=
mplace_back(10);</div><div><br></div><div>We know that this emplaces a vect=
or with ten zeros. How do we know that? Somewhere inside of emplace_back th=
ere is a call to construct() which looks something like this:</div>
<div>template<typename T, typename... A></div><div>void construct(T *=
ptr, A &&... arg)</div><div>{</div><div> new (ptr) T(=
forward<A>(arg)...);</div><div>}</div><div><br></div><div>But what if=
construct looked like this?</div>
<div><br></div>
<div>template<typename T, typename... A></div><div>void construct(T *=
ptr, A &&... arg)</div><div>{</div><div> new (ptr) T{=
forward<A>(arg)...};</div><div>}</div><div><br></div><div>Now the sam=
e code would create a vector that has one element: the number 10.</div>
<div><br></div><div>So for the client to be able to use emplace_back correc=
tly, the client has to know that it will use () and not {} (or in this case=
it has to know that emplace_back uses construct which uses () and not {}).=
And the client usually expects that. If they wanted to use the initializer=
list constructor, they would just do it like this:</div>
<div>a.emplace_back({10});</div><div><br></div><div>Because of this you sho=
uld never initialize using uniform initialization in templated code. If you=
did, then the client wouldn't be able to call some constructors any more.<=
/div>
<div>It sounds like using {^} would behave mostly like () except that it wo=
uld also work for arrays and structs without declared constructors. That's =
cool, but then the client has to know which of the three initializations is=
used in templated code.</div></blockquote><div><br>Why does the client nee=
d to know this? So long as the client provides a type with the required int=
erface, then it will work. That's the point of template code; you provide a=
known interface, and the template uses it.<br><br>`construct` doesn't need=
to care that it actually calls a constructor. You could easily redefine it=
to be {^}, and this would allow it to be used on things that can be unifor=
mly initialized with those parameters. That's a good thing; it would let yo=
u 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; bor=
der-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div cl=
ass=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">struct</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Simple<=
/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: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">int</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> foo</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
bar</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;}</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>std</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">vector</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D=
"color: #606;" class=3D"styled-by-prettify">Simple</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">></span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> v</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>v</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">emplace_back</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">(</span><span style=3D"color: #066;" class=3D"styled-by-prettify">10</=
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: #066;" class=3D"styled-by-prettify">20</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br></span></div></code></div><br>Just as yo=
u could do this:<br><br><div class=3D"prettyprint" style=3D"background-colo=
r: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: soli=
d; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><=
div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">struct</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">S=
imple</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"> </span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">int</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"> </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">int</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><br><=
/span><span style=3D"color: #606;" class=3D"styled-by-prettify">Simple</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> s </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=
: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #066;" =
class=3D"styled-by-prettify">10</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">20</span><span style=3D"color: #660;" class=3D"styled-by-prettify">};</s=
pan></div></code></div><br>This would have been very dangerous for {} synta=
x, because it would prefer initializer_list constructors, thus hiding regul=
ar ones. But with {^} syntax, you can get at the constructors.<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>Currently you can alwa=
ys expect initialization using ().</div></blockquote><div><br>First, no you=
can't. People do use uniform initialization, even in template code.<br><br=
>Second and more importantly, you <i>shouldn't care</i>. All you as the cli=
ent should care about is providing the interface that the template requires=
; it's up to the template writers not to go outside of this interface.<br><=
br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div>Do we want to ma=
ke that more complicated?</div></blockquote><div><br>It doesn't make things=
more complicated; it makes them simpler for the user. On both ends.<br>&nb=
sp;</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div> It might be wor=
th it, but only if we could guarantee that you can really use {^} for EVERY=
THING.</div></blockquote><div><br>You don't need to. You just need a way to=
prefer one kind of constructor over another. The ambiguity will always be =
there; there simply needs to be a way to pick one vs. the other.<br><br>Rig=
ht now, we have a method that only calls constructors (ie: ()), and a metho=
d that can call non-constructor things but will prefer initializer_list con=
structors if one fits. What we need is third way that can call non-construc=
tor things but will prefer non-initializer_list constructors if one fits. W=
hich one that someone wants to use in their template code is up to them.<br=
><br>And yes, technically, it would allow you to access all of the construc=
tion methods, though obviously you would need more braces:<br><br></div><di=
v class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); bord=
er-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">vector</span><s=
pan style=3D"color: #080;" class=3D"styled-by-prettify"><int></span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> v1</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">{^</span><span style=3D"c=
olor: #066;" class=3D"styled-by-prettify">20</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">};</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br>vector</span><span style=3D"color: #080;" cla=
ss=3D"styled-by-prettify"><int></span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> v2</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">{^{^</span><span style=3D"color: #066;" class=3D"styled=
-by-prettify">20</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">}};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br></span></div></code></div><br><br>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_196_16526290.1356900610408--
.
Author: vjacquet@flowgroup.fr
Date: Sun, 6 Jan 2013 02:30:45 -0800 (PST)
Raw View
------=_Part_247_22952712.1357468245603
Content-Type: text/plain; charset=ISO-8859-1
std::vector is a container so I think uniformization of the initialization
is meant to be "like int[]".
IMVHO, I think that using the functional style initialization form of
std::vector<int> intVec1( 43 );
emphases the fact that I am calling a function, as it is a "short cut" for
std::vector<int> intVec1;
intVec1.resize(43);
Therefore I find std::vector<int> intVec1( 43 ); much more readable
than std::vector<int> intVec2{ 43, std::value_init };
On Tuesday, November 13, 2012 1:50:02 AM UTC+1, Nicol Bolas wrote:
>
> Currently, uniform initialization allows you to use {} in virtually all
> cases of initialization. But not all.
>
> Consider:
>
> std::vector<int> intVec1( 43 );
> std::vector<int> intVec2{ 43 };
>
> Do these do the same thing? No. `intVec1` will be a vector containing 43
> value-initialized integers. `intVec2` will be a vector containing a single
> integer who's value is 43.
>
> This happens because an initializer_list constructor, when it fits the
> braced-init-list, takes priority when determining which constructors to
> call. That's a problem.
>
> Now it's important to note that this is only a problem because the type of
> the vector matches the type used for the sizing constructor. Fixing this in
> the language is not going to be possible; a much better fix is to provide
> library support. For example:
>
> std::vector<int> intVec1( 43, std::value_init );
> std::vector<int> intVec2{ 43, std::value_init };
>
> The constructor of `std::vector` that takes a single integer could be
> extended to take an integer and a default parameter value of type
> `std::value_init_t`. And `std::value_init` would be a value of that type.
> The only way this initialization would be non-uniform is if you tried to
> initialize a `vector<std::value_init_t>`s.
>
> I think we can live with that.
>
> The proposal would be to go through each templated standard library type
> that has an initializer_list constructor and see when it could conflict
> with other constructors. In those cases, add a default parameter of some
> standard library type to disambiguate it.
>
--
------=_Part_247_22952712.1357468245603
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div>std::vector is a container so I think uniformization of the initializa=
tion is meant to be "like int[]". </div><div><br></div><div>IMVHO, I t=
hink that using the functional style initialization form of </div=
><div>std::vector<int> intVec1( 43 ); <br></div><=
div><br></div><div>emphases the fact that I am calling a function, as it is=
a "short cut" for</div><div>std::vector<int> intVec1;<br></div><div>=
intVec1.resize(43);</div><div><br></div><div>Therefore I find std::vec=
tor<int> intVec1( 43 ); much more readable than std::vector=
<int> intVec2{ 43, std::value_init };</div><br>On Tuesday, November 1=
3, 2012 1:50:02 AM UTC+1, Nicol Bolas wrote:<blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;">Currently, uniform initialization allows you to use {} in vir=
tually all cases of initialization. But not all.<br><br>Consider:<br><br>st=
d::vector<int> intVec1( 43 );<br>std::vector<int> intVec2{ 43 }=
;<br><br>Do these do the same thing? No. `intVec1` will be a vector contain=
ing 43 value-initialized integers. `intVec2` will be a vector containing a =
single integer who's value is 43.<br><br>This happens because an initialize=
r_list constructor, when it fits the braced-init-list, takes priority when =
determining which constructors to call. That's a problem.<br><br>Now it's i=
mportant to note that this is only a problem because the type of the vector=
matches the type used for the sizing constructor. Fixing this in the langu=
age is not going to be possible; a much better fix is to provide library su=
pport. For example:<br><br>std::vector<int> intVec1( 43, std::value_i=
nit );<br>std::vector<int> intVec2{ 43, std::value_init };<br><br>The=
constructor of `std::vector` that takes a single integer could be extended=
to take an integer and a default parameter value of type `std::value_init_=
t`. And `std::value_init` would be a value of that type. The only way this =
initialization would be non-uniform is if you tried to initialize a `vector=
<std::value_init_t>`s.<br><br>I think we can live with that.<br><br>T=
he proposal would be to go through each templated standard library type tha=
t has an initializer_list constructor and see when it could conflict with o=
ther constructors. In those cases, add a default parameter of some standard=
library type to disambiguate it.<br></blockquote>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_247_22952712.1357468245603--
.