Topic: RFC: More uniform initialization with std::construct
Author: Tristan Brindle <tcbrindle@gmail.com>
Date: Wed, 25 May 2016 09:42:57 -0700 (PDT)
Raw View
------=_Part_174_709875473.1464194577028
Content-Type: multipart/alternative;
boundary="----=_Part_175_1236060472.1464194577029"
------=_Part_175_1236060472.1464194577029
Content-Type: text/plain; charset=UTF-8
tl;dr
I'd like to propose a std::construct() function to make it easier to use
aggregate types in generic
code, along with a couple of supporting type traits.
Motivation
With the addition of NSDMIs for aggregates in C++14, simple structs with no
user-defined constructors
are more useful than ever. Unfortunately, such aggregates are difficult to
use in generic code. For example:
struct example {
int i = 0;
double d = 0.0;
};
auto p = std::make_unique<example>(3, 4.0); // error: no matching function for call to 'example::example(int, double)'
std::vector<example> vec;
vec.emplace_back(3, 4.0); // error: no matching function for call to 'example::example(int, double)'
static_assert(std::is_constructible<example, int, double>::value, ""); // fails
These problems stem from the fact that in generic code, one must make a choice of whether to use
*direct-initialization* style T(args...) or *list-initialization* style T{args...} when constructing a new value.
The former leads to the inability to use types without user-defined constructors, while the latter leads to
unexpected behaviour with types that have a constructor taking a std::initializer_list, as the T{args...} form
will always prefer such a constructor. This being the case, generic code (including all cases in the
standard library, as far as I know) invariably opts for the T(args...) form.
A Solution (1)
Since std::is_constructible is specified to use the *direct-initialization* form, it would appear to be enough
to specify that if std::constructible<T, Args...>::value == false, then the *list-initialization* form should be tried
instead. However,this would lead to initializer_list constructors being called in situations where it may not be
expected.
For example, if std::make_unique() were to fall back to calling T{args...} if std::is_constructible is false, then
auto p = std::make_unique<std::vector<int>>(1, 2, 3, 4, 5); // Works!?
In this scenario, an initializer_list constructor would never be preferred to an ordinary constructor; however, it
would lead to code which fails today compiling tomorrow, which may be unexpected. Whether this is
acceptable -- or perhaps even desirable -- would be a matter for the committee to decide.
Another Solution (2)
A slightly more complex alternative which avoids the above problem would be to add a new type trait,
template <class T>
struct has_initializer_list_constructor;
which is std::true_type if T has any constructor taking an intializer_list. Such a type trait would probably need
compiler magic to implement (at least, I can't think of any way of doing so generically, but perhaps
others can). While I'm not a compiler developer, I don't think this should be a deal-breaker: several other type
traits already require compiler magic, and the compiler already needs to know whether a type has an
initializer_list constructor in order to decide what to do when it sees T{args...}.
With this type trait, we can reverse the logic of solution 1, and use T{args...} except when
has_initializer_list_constructor<T>::value is true, in which case we use T(args...). Since both construction
forms do the same thing absent an initializer_list constructor (except that the former works for aggregates),
this solution should not lead to any unexpected constructor calls.
A Proposal
My preference is for the second solution, so let's imagine that this is chosen. In this case, we would have a
short algorithm to use when constructing new values in generic code:
- If T is constructible from T{args...} and has_initializer_list_constructor::value is false, the call T{args...}
- Otherwise, call T(args...)
In order to support the first part, it would be handy to add another new trait
template <typename T, typename... Args>
struct is_list_constructible;
in order to detect whether such a *list-initialization* style call is valid. This would have the exact same requirements
as is_constructible, except with "curly braces" rather than "round brackets". It would probably also be
desirable to add is_trivially_list_constructible and is_nothrow_list_constructible for symmetry with the
existing traits.
To make it easy to use this algorithm in practise, and to increase code re-use, the logic could be
encoded into a new standard library function, std::construct():
template <class T, class... Args>
T construct(Args&&... args)
This function would be specified to return a new T
- using T{std::forward<Args>(args)...} if std::has_initializer_list_constructor::value == false, and
- using T(std::forward<Args>(args)...) if std::has_initializer_list_constructor::value == true
One could view std::construct() as being a generalised constructor call in much the same way that
std::invoke() is a generalised function call. As with std::invoke() (and the INVOKE algorithm that
preceded it), standard library functions which forward arguments to constructors (such as
std::make_unique()) could be specified to behave "as if" they called std::construct().
Conclusion
Uniform initialization, introduced in C++11, is unfortunately not
particularly at all uniform thanks to
std::initializer_list constructors. (If nothing else, a type trait to
detect when such a constructor is present
on a type would be beneficial by itself.) A std::construct() function which
"does what you want"
would finally allow *truly* uniform initialization for all C++ types,
including simple aggregates. Let's do it.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6a617f44-dcfa-4b67-aff8-52397ee13431%40isocpp.org.
------=_Part_175_1236060472.1464194577029
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div><font size=3D"4">tl;dr</font></div><div><br></div=
><div>I'd like to propose a <font face=3D"courier new, monospace">std::=
construct() </font>function to make it easier to use aggregate types in gen=
eric</div><div>code, along with a couple of supporting type traits.</div><d=
iv><br></div><div><font size=3D"4">Motivation</font></div><div><br></div><d=
iv>With the addition of NSDMIs for aggregates in C++14, simple structs with=
no user-defined constructors</div><div>are more useful than ever. Unfortun=
ately, such aggregates are difficult to use in generic code. For example:</=
div><div><br></div><div>
<pre><!--StartFragment--><span style=3D" color:#808000;"> struct</span><=
span style=3D" color:#c0c0c0;"> </span><span style=3D" color:#800080;">exam=
ple</span><span style=3D" color:#c0c0c0;"> </span><span style=3D" color:#00=
0000;">{</span></pre>
<pre><span style=3D" color:#c0c0c0;"> </span><span style=3D" color:#=
808000;">int</span><span style=3D" color:#c0c0c0;"> </span><span style=3D" =
color:#800000;">i</span><span style=3D" color:#c0c0c0;"> </span><span style=
=3D" color:#000000;">=3D</span><span style=3D" color:#c0c0c0;"> </span><spa=
n style=3D" color:#000080;">0</span><span style=3D" color:#000000;">;</span=
></pre>
<pre><span style=3D" color:#c0c0c0;"> </span><span style=3D" color:#=
808000;">double</span><span style=3D" color:#c0c0c0;"> </span><span style=
=3D" color:#800000;">d</span><span style=3D" color:#c0c0c0;"> </span><span =
style=3D" color:#000000;">=3D</span><span style=3D" color:#c0c0c0;"> </span=
><span style=3D" color:#000080;">0.0</span><span style=3D" color:#000000;">=
;</span></pre>
<pre><span style=3D" color:#000000;"> };</span><!--EndFragment--></pre><=
pre><br></pre><pre><pre><!--StartFragment--><span style=3D" color:#808000;"=
> auto</span><span style=3D" color:#c0c0c0;"> </span><span style=3D" col=
or:#000000;">p</span><span style=3D" color:#c0c0c0;"> </span><span style=3D=
" color:#000000;">=3D</span><span style=3D" color:#c0c0c0;"> </span>std<spa=
n style=3D" color:#000000;">::</span>make_unique<span style=3D" color:#0000=
00;"><</span>example<span style=3D" color:#000000;">>(</span><span st=
yle=3D" color:#000080;">3</span><span style=3D" color:#000000;">,</span><sp=
an style=3D" color:#c0c0c0;"> </span><span style=3D" color:#000080;">4.0</s=
pan><span style=3D" color:#000000;">); // </span><font color=3D"#000000">er=
ror: no matching function for call to 'example::example(int, double)=
9;</font><!--EndFragment--></pre><pre><br></pre><pre> std::vector<exa=
mple> vec;
vec.emplace_back(3, 4.0); // error: no matching function for call to &#=
39;example::example(int, double)'<br></pre><pre><br></pre><pre> stat=
ic_assert(std::is_constructible<example, int, double>::value, "&=
quot;); // fails</pre><pre><br></pre><pre><font face=3D"arial, sans-serif">=
These problems stem from the fact that in generic code, one must make a cho=
ice of whether to use </font></pre><pre><font face=3D"arial, sans-serif"><i=
>direct-initialization</i> style </font><font face=3D"courier new, monospac=
e">T(args...) </font><font face=3D"arial, sans-serif">or <i>list-initializa=
tion</i> style </font><font face=3D"courier new, monospace">T{args...}</fon=
t><font face=3D"arial, sans-serif"> when constructing a new value.</font></=
pre><pre><font face=3D"arial, sans-serif">The former leads to the inability=
to </font><span style=3D"font-family: arial, sans-serif;">use types withou=
t user-defined constructors, while the latter leads to</span></pre><pre><sp=
an style=3D"font-family: arial, sans-serif;">unexpected behaviour with type=
s </span><span style=3D"font-family: arial, sans-serif;">that have a constr=
uctor taking a </span><font face=3D"courier new, monospace">std::initialize=
r_list</font><span style=3D"font-family: arial, sans-serif;">, as the </spa=
n><font face=3D"courier new, monospace">T{args...}</font><span style=3D"fon=
t-family: arial, sans-serif;"> form</span></pre><pre><span style=3D"font-fa=
mily: arial, sans-serif;">will always prefer such </span><span style=3D"fon=
t-family: arial, sans-serif;">a constructor. This being the case, generic c=
ode (including all cases in the=C2=A0</span></pre><pre><span style=3D"font-=
family: arial, sans-serif;">standard library, as far as I know) invariably =
opts for the </span><font face=3D"courier new, monospace">T(args...)</font>=
<span style=3D"font-family: arial, sans-serif;"> form.</span></pre><pre><fo=
nt face=3D"arial, sans-serif"><br></font></pre><pre><font face=3D"arial, sa=
ns-serif" size=3D"4">A Solution (1)</font></pre><pre><font face=3D"arial, s=
ans-serif"><br></font></pre><pre><font face=3D"arial, sans-serif">Since </f=
ont><font face=3D"courier new, monospace">std::is_constructible</font><font=
face=3D"arial, sans-serif"> is specified to use the <i>direct-initializati=
on</i> form, it would appear to be enough</font></pre><pre><font face=3D"ar=
ial, sans-serif">to specify that if </font><font face=3D"courier new, monos=
pace">std::constructible<T, Args...>::value =3D=3D false</font><font =
face=3D"arial, sans-serif">, then the <i>list-initialization</i> form shoul=
d be tried</font></pre><pre><font face=3D"arial, sans-serif">instead. Howev=
er,</font><span style=3D"font-family: arial, sans-serif;">this would lead t=
o </span><font face=3D"courier new, monospace">initializer_list</font><span=
style=3D"font-family: arial, sans-serif;"> constructors being called in si=
tuations where it may not be</span></pre><pre><span style=3D"font-family: a=
rial, sans-serif;">expected.</span></pre><pre><font face=3D"arial, sans-ser=
if"><br></font></pre><pre><font face=3D"arial, sans-serif">For example, if =
</font><font face=3D"courier new, monospace">std::make_unique()</font><font=
face=3D"arial, sans-serif"> were to fall back to calling </font><font face=
=3D"courier new, monospace">T{args...}</font><font face=3D"arial, sans-seri=
f"> if </font><font face=3D"courier new, monospace">std::is_constructible</=
font><font face=3D"arial, sans-serif"> is false, then</font></pre><pre><br>=
</pre><pre><!--StartFragment--><span style=3D" color:#808000;"> auto</sp=
an><span style=3D" color:#c0c0c0;"> </span><span style=3D" color:#000000;">=
p</span><span style=3D" color:#c0c0c0;"> </span><span style=3D" color:#0000=
00;">=3D</span><span style=3D" color:#c0c0c0;"> </span>std<span style=3D" c=
olor:#000000;">::</span>make_unique<span style=3D" color:#000000;"><</sp=
an>std<span style=3D" color:#000000;">::</span>vector<span style=3D" color:=
#000000;"><</span><span style=3D" color:#808000;">int</span><span style=
=3D" color:#000000;">>>(</span><span style=3D" color:#000080;">1</spa=
n><span style=3D" color:#000000;">,</span><span style=3D" color:#c0c0c0;"> =
</span><span style=3D" color:#000080;">2</span><span style=3D" color:#00000=
0;">,</span><span style=3D" color:#c0c0c0;"> </span><span style=3D" color:#=
000080;">3, 4, 5</span><span style=3D" color:#000000;">); // Works!?</span>=
<!--EndFragment--></pre><pre><font face=3D"arial, sans-serif"><br></font></=
pre><pre><font face=3D"arial, sans-serif">In this scenario, an </font><font=
face=3D"courier new, monospace">initializer_list</font><font face=3D"arial=
, sans-serif"> constructor would never be preferred to an ordinary construc=
tor; however, it</font></pre><pre><font face=3D"arial, sans-serif">would le=
ad to code which fails today compiling tomorrow, which may be unexpected. W=
hether this is</font></pre><pre><font face=3D"arial, sans-serif">acceptable=
-- or perhaps even desirable -- would be a matter for the committee to dec=
ide.</font></pre><pre><font face=3D"arial, sans-serif"><br></font></pre><pr=
e><font face=3D"arial, sans-serif" size=3D"4">Another Solution (2)</font></=
pre><pre><font face=3D"arial, sans-serif"><br></font></pre><pre><font face=
=3D"arial, sans-serif">A slightly more complex alternative which avoids the=
above problem would be to add a new type trait,</font></pre><pre><br></pre=
><pre><pre> <span style=3D" color:#808000;">template</span><span style=
=3D" color:#c0c0c0;"> </span><span style=3D" color:#000000;"><</span><sp=
an style=3D" color:#808000;">class</span><span style=3D" color:#c0c0c0;"> <=
/span><span style=3D" color:#800080;">T</span><span style=3D" color:#000000=
;">></span></pre><pre><span style=3D" color:#808000;"> struct</span><=
span style=3D" color:#c0c0c0;"> </span><span style=3D" color:#800080;">has_=
initializer_list_constructor</span><span style=3D" color:#000000;">;</span>=
<!--EndFragment--></pre><pre><span style=3D" color:#000000;"><br></span></p=
re><pre><font face=3D"arial, sans-serif">which is </font><font face=3D"cour=
ier new, monospace">std::true_type</font><font face=3D"arial, sans-serif"> =
if </font><font face=3D"courier new, monospace">T</font><font face=3D"arial=
, sans-serif"> has any constructor taking an </font><font face=3D"courier n=
ew, monospace">intializer_list</font><span style=3D"font-family: arial, san=
s-serif;">. Such a type trait would probably need</span></pre><pre><font fa=
ce=3D"arial, sans-serif">compiler magic to implement (at least, I can't=
think of any way of doing so generically, but perhaps</font></pre><pre><fo=
nt face=3D"arial, sans-serif">others can). While I'm not a compiler dev=
eloper, I don't think this should be a deal-breaker: several other type=
</font></pre><pre><font face=3D"arial, sans-serif">traits already require c=
ompiler magic, and the compiler already needs to know whether a type has an=
</font></pre><pre><font face=3D"courier new, monospace">initializer_list</f=
ont><font face=3D"arial, sans-serif"> constructor in order to decide what t=
o do when it sees </font><font face=3D"courier new, monospace">T{args...}</=
font><font face=3D"arial, sans-serif">.</font></pre><pre><br></pre><pre><fo=
nt face=3D"arial, sans-serif">With this type trait, we can reverse the logi=
c of solution 1, and use </font><font face=3D"courier new, monospace">T{arg=
s...}</font><font face=3D"arial, sans-serif"> except when</font></pre><pre>=
<font face=3D"courier new, monospace">has_initializer_list_constructor<T=
>::value</font><font face=3D"arial, sans-serif"> is true, in which case =
we use </font><font face=3D"courier new, monospace">T(args...)</font><font =
face=3D"arial, sans-serif">. Since both construction</font></pre><pre><font=
face=3D"arial, sans-serif">forms do the same thing absent an </font><font =
face=3D"courier new, monospace">initializer_list</font><font face=3D"arial,=
sans-serif"> constructor (except that the former works for aggregates),</f=
ont></pre><pre><font face=3D"arial, sans-serif">this solution should not le=
ad to any unexpected constructor calls.</font></pre><pre><font face=3D"aria=
l, sans-serif"><br></font></pre><pre><font face=3D"arial, sans-serif" size=
=3D"4">A Proposal</font></pre><pre><br></pre><pre><font face=3D"arial, sans=
-serif">My preference is for the second solution, so let's imagine that=
this is chosen. In this case, we would have a</font></pre><pre><font face=
=3D"arial, sans-serif">short algorithm to use when constructing new values =
in generic code:</font></pre><pre><ul><li><span style=3D"line-height: norma=
l;"><font face=3D"arial, sans-serif">If </font><font face=3D"courier new, m=
onospace">T</font><font face=3D"arial, sans-serif"> is constructible from <=
/font><font face=3D"courier new, monospace">T{args...}</font><font face=3D"=
arial, sans-serif"> and </font><font face=3D"courier new, monospace">has_in=
itializer_list_constructor::value</font><font face=3D"arial, sans-serif"> i=
s false, the call </font><font face=3D"courier new, monospace">T{args...}</=
font></span></li><li><span style=3D"line-height: normal;"><font face=3D"ari=
al, sans-serif">Otherwise, call </font><font face=3D"courier new, monospace=
">T(args...)</font></span></li></ul><div><font face=3D"arial, sans-serif">I=
n order to support the first part, it would be handy to add another new tra=
it</font></div><div><br></div><div><pre> <span style=3D" color:#808000;"=
>template</span><span style=3D" color:#c0c0c0;"> </span><span style=3D" col=
or:#000000;"><</span><span style=3D" color:#808000;">typename</span><spa=
n style=3D" color:#c0c0c0;"> </span><span style=3D" color:#800080;">T</span=
><span style=3D" color:#000000;">,</span><span style=3D" color:#c0c0c0;"> <=
/span><span style=3D" color:#808000;">typename</span><span style=3D" color:=
#000000;">...</span><span style=3D" color:#c0c0c0;"> </span><span style=3D"=
color:#800080;">Args</span><span style=3D" color:#000000;">></span></pr=
e><pre><span style=3D" color:#808000;"> struct</span><span style=3D" col=
or:#c0c0c0;"> </span><span style=3D" color:#800080;">is_list_constructible<=
/span><span style=3D" color:#000000;">;</span><!--EndFragment--></pre></div=
></pre><pre><br></pre><pre><font face=3D"arial, sans-serif">in order to det=
ect whether such a <i>list-initialization</i> style call is valid. This wou=
ld have the exact same requirements</font></pre><pre><font face=3D"arial, s=
ans-serif">as i</font><font face=3D"courier new, monospace">s_constructible=
</font><font face=3D"arial, sans-serif">, except with "curly braces&qu=
ot; rather than "round brackets". It would probably also be</font=
></pre><pre><font face=3D"arial, sans-serif">desirable to add </font><font =
face=3D"courier new, monospace">is_trivially_list_constructible</font><font=
face=3D"arial, sans-serif"> and </font><font face=3D"courier new, monospac=
e">is_nothrow_list_constructible</font><font face=3D"arial, sans-serif"> fo=
r symmetry with the</font></pre><pre><font face=3D"arial, sans-serif">exist=
ing traits.</font></pre><pre><br></pre><pre><font face=3D"arial, sans-serif=
">To make it easy to use this algorithm in practise, and to increase code r=
e-use, the logic could be</font></pre><pre><font face=3D"arial, sans-serif"=
>encoded into a new standard library function, </font><font face=3D"courier=
new, monospace">std::construct()</font><font face=3D"arial, sans-serif">:<=
/font></pre>
<pre><!--StartFragment--><span style=3D" color:#808000;"> template</span=
><span style=3D" color:#c0c0c0;"> </span><span style=3D" color:#000000;">&l=
t;</span><span style=3D" color:#808000;">class</span><span style=3D" color:=
#c0c0c0;"> </span><span style=3D" color:#800080;">T</span><span style=3D" c=
olor:#000000;">,</span><span style=3D" color:#c0c0c0;"> </span><span style=
=3D" color:#808000;">class</span><span style=3D" color:#000000;">...</span>=
<span style=3D" color:#c0c0c0;"> </span><span style=3D" color:#800080;">Arg=
s</span><span style=3D" color:#000000;">></span></pre><pre><span style=
=3D" color:#800080;"> T</span><span style=3D" color:#c0c0c0;"> </span><s=
pan style=3D" color:#000000;">construct</span><span style=3D" color:#000000=
;">(</span><span style=3D" color:#800080;">Args</span><span style=3D" color=
:#000000;">&&...</span><span style=3D" color:#c0c0c0;"> </span><spa=
n style=3D" color:#000000;">args</span><span style=3D" color:#000000;">)</s=
pan><!--EndFragment--></pre><pre><font face=3D"arial, sans-serif"><br></fon=
t></pre><pre><font face=3D"arial, sans-serif">This function would be specif=
ied to return a new </font><font face=3D"courier new, monospace">T</font></=
pre><pre><ul><li><span style=3D"font-family: arial, sans-serif;">using </sp=
an><font face=3D"courier new, monospace">T{std::forward<Args>(args)..=
..}</font><span style=3D"font-family: arial, sans-serif;"> if </span><font f=
ace=3D"courier new, monospace">std::has_initializer_list_constructor::value=
=3D=3D false</font><span style=3D"font-family: arial, sans-serif;">, and</=
span></li><li><font face=3D"arial, sans-serif">using </font><font face=3D"c=
ourier new, monospace">T(std::forward<Args>(args)...)</font><font fac=
e=3D"arial, sans-serif"> if </font><font face=3D"courier new, monospace">st=
d::has_initializer_list_constructor::value =3D=3D true</font></li></ul><div=
><font face=3D"arial, sans-serif"><span style=3D"line-height: 17px;"><br></=
span></font></div><div><pre><div><span style=3D"font-family: arial, sans-se=
rif; line-height: 17px;">One could view</span><span style=3D"line-height: 1=
7px;"><font face=3D"courier new, monospace"> std::construct()</font></span>=
<span style=3D"font-family: arial, sans-serif; line-height: 17px;"> as bein=
g a generalised constructor call in much the same way that</span><br></div>=
<div><pre><span style=3D"line-height: 17px;"><font face=3D"courier new, mon=
ospace">std::invoke()</font><font face=3D"arial, sans-serif"> is a generali=
sed function call. As with </font><font face=3D"courier new, monospace">std=
::invoke()</font><font face=3D"arial, sans-serif"> (and the INVOKE algorith=
m that </font></span></pre><pre><span style=3D"line-height: 17px;"><font fa=
ce=3D"arial, sans-serif">preceded it), standard library functions which for=
ward arguments to constructors (such as</font></span></pre><pre><span style=
=3D"line-height: 17px;"><font face=3D"courier new, monospace">std::make_uni=
que()</font><font face=3D"arial, sans-serif">) could be specified to behave=
"as if" they called </font><font face=3D"courier new, monospace"=
>std::construct()</font><font face=3D"arial, sans-serif">.</font></span></p=
re></div></pre></div><div><font face=3D"arial, sans-serif"><span style=3D"l=
ine-height: 17px;"><br></span></font></div><div><font face=3D"arial, sans-s=
erif" size=3D"4"><span style=3D"line-height: 17px;">Conclusion</span></font=
></div><div><br></div><div><font face=3D"arial, sans-serif">Uniform initial=
ization, introduced in C++11, is unfortunately not particularly at all unif=
orm thanks to</font></div><div><font face=3D"courier new, monospace">std::i=
nitializer_list</font><span style=3D"font-family: arial, sans-serif;"> cons=
tructors. (If nothing else, a type trait to detect when such a constructor =
is present</span></div><div><span style=3D"font-family: arial, sans-serif;"=
>on a type would be beneficial by itself.) A </span><font face=3D"courier n=
ew, monospace">std::construct()</font><span style=3D"font-family: arial, sa=
ns-serif;"> function which "does what you want"</span></div><div>=
<span style=3D"font-family: arial, sans-serif;">would finally allow <b>trul=
y</b> uniform initialization for all C++ types, including simple aggregates=
.. Let's do it.</span></div><div><span style=3D"font-family: arial, sans=
-serif;"><br></span></div></pre></pre></pre></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/6a617f44-dcfa-4b67-aff8-52397ee13431%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/6a617f44-dcfa-4b67-aff8-52397ee13431=
%40isocpp.org</a>.<br />
------=_Part_175_1236060472.1464194577029--
------=_Part_174_709875473.1464194577028--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Wed, 25 May 2016 20:28:01 +0200
Raw View
This is a multi-part message in MIME format.
--------------38A9DAC464565FE1C9147451
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 25/05/2016 =C3=A0 18:42, Tristan Brindle a =C3=A9crit :
>
> tl;dr
>
> I'd like to propose a std::construct() function to make it easier to=20
> use aggregate types in generic
> code, along with a couple of supporting type traits.
>
> Motivation
>
> With the addition of NSDMIs for aggregates in C++14, simple structs=20
> with no user-defined constructors
> are more useful than ever. Unfortunately, such aggregates are=20
> difficult to use in generic code. For example:
>
> structexample{
> inti=3D0;
> doubled=3D0.0;
> };
> autop=3Dstd::make_unique<example>(3,4.0); // error: no matching function =
for call to=20
> 'example::example(int, double)'
> std::vector<example> vec;
> vec.emplace_back(3, 4.0); // error: no matching function for call to=
'example::example(int, double)'
> static_assert(std::is_constructible<example, int, double>::value, ""=
); // fails
> These problems stem from the fact that in generic code, one must make=20
> a choice of whether to use
> /direct-initialization/ style T(args...) or /list-initialization/=20
> style T{args...}when constructing a new value.
> The former leads to the inability to use types without user-defined=20
> constructors, while the latter leads to
> unexpected behaviour with types that have a constructor taking a=20
> std::initializer_list, as the T{args...}form
> will always prefer such a constructor. This being the case, generic=20
> code (including all cases in the
> standard library, as far as I know) invariably opts for the=20
> T(args...)form.
> <snip>
> To make it easy to use this algorithm in practise, and to increase=20
> code re-use, the logic could be
> encoded into a new standard library function, std::construct():
>
> template<classT,class...Args>
> Tconstruct(Args&&...args)
> This function would be specified to return a new T
>
> * using T{std::forward<Args>(args)...}if
> std::has_initializer_list_constructor::value =3D=3D false, and
> * using T(std::forward<Args>(args)...)if
> std::has_initializer_list_constructor::value =3D=3D true
>
> One could viewstd::construct()as being a generalised constructor call=20
> in much the same way that
> std::invoke()is a generalised function call. As with std::invoke()(and=20
> the INVOKE algorithm that
> preceded it), standard library functions which forward arguments to=20
> constructors (such as
> std::make_unique()) could be specified to behave "as if" they called=20
> std::construct().
> Conclusion
> Uniform initialization, introduced in C++11, is unfortunately not=20
> particularly at all uniform thanks to
> std::initializer_listconstructors. (If nothing else, a type trait to=20
> detect when such a constructor is present
> on a type would be beneficial by itself.) A std::construct()function=20
> which "does what you want"
> would finally allow *truly* uniform initialization for all C++ types,=20
> including simple aggregates. Let's do it.
Hi,
I would like to see this proposal in Oulu. I have a proposal for generic=20
make factories [1] that could use the proposed std::constructor instead=20
of using the using direct-initialization.
My proposal is similar, but allows the user to customize the creation of=20
the instance. This is useful in particular when the class has no=20
constructor but has factories as future.
I also prefer the alternative (2).
I would add that in addition your proposal provides a function to call a=20
constructor which can be used is some algorithms.
Best,
Vicente
[1]=20
https://github.com/viboes/std-make/blob/master/doc/proposal/factories/p0338=
r0.md
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/b35314f6-2cd5-4f90-c8de-a53849a2f495%40wanadoo.f=
r.
--------------38A9DAC464565FE1C9147451
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 25/05/2016 =C3=A0 18:42, Tristan Brin=
dle
a =C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:6a617f44-dcfa-4b67-aff8-52397ee13431@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
<div><font size=3D"4">tl;dr</font></div>
<div><br>
</div>
<div>I'd like to propose a <font face=3D"courier new, monospace">st=
d::construct()
</font>function to make it easier to use aggregate types in
generic</div>
<div>code, along with a couple of supporting type traits.</div>
<div><br>
</div>
<div><font size=3D"4">Motivation</font></div>
<div><br>
</div>
<div>With the addition of NSDMIs for aggregates in C++14, simple
structs with no user-defined constructors</div>
<div>are more useful than ever. Unfortunately, such aggregates
are difficult to use in generic code. For example:</div>
<div><br>
</div>
<div>
<pre><!--StartFragment--><span style=3D" color:#808000;"> stru=
ct</span><span style=3D" color:#c0c0c0;"> </span><span style=3D" color:#800=
080;">example</span><span style=3D" color:#c0c0c0;"> </span><span style=3D"=
color:#000000;">{</span></pre>
<pre><span style=3D" color:#c0c0c0;"> </span><span style=
=3D" color:#808000;">int</span><span style=3D" color:#c0c0c0;"> </span><spa=
n style=3D" color:#800000;">i</span><span style=3D" color:#c0c0c0;"> </span=
><span style=3D" color:#000000;">=3D</span><span style=3D" color:#c0c0c0;">=
</span><span style=3D" color:#000080;">0</span><span style=3D" color:#0000=
00;">;</span></pre>
<pre><span style=3D" color:#c0c0c0;"> </span><span style=
=3D" color:#808000;">double</span><span style=3D" color:#c0c0c0;"> </span><=
span style=3D" color:#800000;">d</span><span style=3D" color:#c0c0c0;"> </s=
pan><span style=3D" color:#000000;">=3D</span><span style=3D" color:#c0c0c0=
;"> </span><span style=3D" color:#000080;">0.0</span><span style=3D" color:=
#000000;">;</span></pre>
<pre><span style=3D" color:#000000;"> };</span><!--EndFragment=
--></pre>
<pre>
</pre>
<pre><pre><!--StartFragment--><span style=3D" color:#808000;"> =
auto</span><span style=3D" color:#c0c0c0;"> </span><span style=3D" color:#=
000000;">p</span><span style=3D" color:#c0c0c0;"> </span><span style=3D" co=
lor:#000000;">=3D</span><span style=3D" color:#c0c0c0;"> </span>std<span st=
yle=3D" color:#000000;">::</span>make_unique<span style=3D" color:#000000;"=
><</span>example<span style=3D" color:#000000;">>(</span><span style=
=3D" color:#000080;">3</span><span style=3D" color:#000000;">,</span><span =
style=3D" color:#c0c0c0;"> </span><span style=3D" color:#000080;">4.0</span=
><span style=3D" color:#000000;">); // </span><font color=3D"#000000">error=
: no matching function for call to 'example::example(int, double)'</font><!=
--EndFragment--></pre><pre>
</pre><pre> std::vector<example> vec;
vec.emplace_back(3, 4.0); // error: no matching function for call to 'e=
xample::example(int, double)'
</pre><pre>
</pre><pre> static_assert(std::is_constructible<example, int, double&=
gt;::value, ""); // fails</pre><pre>
</pre><pre><font face=3D"arial, sans-serif">These problems stem from the fa=
ct that in generic code, one must make a choice of whether to use </font></=
pre><pre><font face=3D"arial, sans-serif"><i>direct-initialization</i> styl=
e </font><font face=3D"courier new, monospace">T(args...) </font><font face=
=3D"arial, sans-serif">or <i>list-initialization</i> style </font><font fac=
e=3D"courier new, monospace">T{args...}</font><font face=3D"arial, sans-ser=
if"> when constructing a new value.</font></pre><pre><font face=3D"arial, s=
ans-serif">The former leads to the inability to </font><span style=3D"font-=
family: arial, sans-serif;">use types without user-defined constructors, wh=
ile the latter leads to</span></pre><pre><span style=3D"font-family: arial,=
sans-serif;">unexpected behaviour with types </span><span style=3D"font-fa=
mily: arial, sans-serif;">that have a constructor taking a </span><font fac=
e=3D"courier new, monospace">std::initializer_list</font><span style=3D"fon=
t-family: arial, sans-serif;">, as the </span><font face=3D"courier new, mo=
nospace">T{args...}</font><span style=3D"font-family: arial, sans-serif;"> =
form</span></pre><pre><span style=3D"font-family: arial, sans-serif;">will =
always prefer such </span><span style=3D"font-family: arial, sans-serif;">a=
constructor. This being the case, generic code (including all cases in the=
=C2=A0</span></pre><pre><span style=3D"font-family: arial, sans-serif;">sta=
ndard library, as far as I know) invariably opts for the </span><font face=
=3D"courier new, monospace">T(args...)</font><span style=3D"font-family: ar=
ial, sans-serif;"> form.</span></pre><pre><font face=3D"arial, sans-serif">
</font></pre><snip><pre><pre><font face=3D"arial, sans-serif">To make=
it easy to use this algorithm in practise, and to increase code re-use, th=
e logic could be</font></pre><pre><font face=3D"arial, sans-serif">encoded =
into a new standard library function, </font><font face=3D"courier new, mon=
ospace">std::construct()</font><font face=3D"arial, sans-serif">:</font></p=
re>
<pre><!--StartFragment--><span style=3D" color:#808000;"> template</span=
><span style=3D" color:#c0c0c0;"> </span><span style=3D" color:#000000;">&l=
t;</span><span style=3D" color:#808000;">class</span><span style=3D" color:=
#c0c0c0;"> </span><span style=3D" color:#800080;">T</span><span style=3D" c=
olor:#000000;">,</span><span style=3D" color:#c0c0c0;"> </span><span style=
=3D" color:#808000;">class</span><span style=3D" color:#000000;">...</span>=
<span style=3D" color:#c0c0c0;"> </span><span style=3D" color:#800080;">Arg=
s</span><span style=3D" color:#000000;">></span></pre><pre><span style=
=3D" color:#800080;"> T</span><span style=3D" color:#c0c0c0;"> </span><s=
pan style=3D" color:#000000;">construct</span><span style=3D" color:#000000=
;">(</span><span style=3D" color:#800080;">Args</span><span style=3D" color=
:#000000;">&&...</span><span style=3D" color:#c0c0c0;"> </span><spa=
n style=3D" color:#000000;">args</span><span style=3D" color:#000000;">)</s=
pan><!--EndFragment--></pre><pre><font face=3D"arial, sans-serif">
</font></pre><pre><font face=3D"arial, sans-serif">This function would be s=
pecified to return a new </font><font face=3D"courier new, monospace">T</fo=
nt></pre><pre><ul><li><span style=3D"font-family: arial, sans-serif;">using=
</span><font face=3D"courier new, monospace">T{std::forward<Args>(ar=
gs)...}</font><span style=3D"font-family: arial, sans-serif;"> if </span><f=
ont face=3D"courier new, monospace">std::has_initializer_list_constructor::=
value =3D=3D false</font><span style=3D"font-family: arial, sans-serif;">, =
and</span></li><li><font face=3D"arial, sans-serif">using </font><font face=
=3D"courier new, monospace">T(std::forward<Args>(args)...)</font><fon=
t face=3D"arial, sans-serif"> if </font><font face=3D"courier new, monospac=
e">std::has_initializer_list_constructor::value =3D=3D true</font></li></ul=
><div><font face=3D"arial, sans-serif"><span style=3D"line-height: 17px;">
</span></font></div><div><pre><div><span style=3D"font-family: arial, sans-=
serif; line-height: 17px;">One could view</span><span style=3D"line-height:=
17px;"><font face=3D"courier new, monospace"> std::construct()</font></spa=
n><span style=3D"font-family: arial, sans-serif; line-height: 17px;"> as be=
ing a generalised constructor call in much the same way that</span>
</div><div><pre><span style=3D"line-height: 17px;"><font face=3D"courier ne=
w, monospace">std::invoke()</font><font face=3D"arial, sans-serif"> is a ge=
neralised function call. As with </font><font face=3D"courier new, monospac=
e">std::invoke()</font><font face=3D"arial, sans-serif"> (and the INVOKE al=
gorithm that </font></span></pre><pre><span style=3D"line-height: 17px;"><f=
ont face=3D"arial, sans-serif">preceded it), standard library functions whi=
ch forward arguments to constructors (such as</font></span></pre><pre><span=
style=3D"line-height: 17px;"><font face=3D"courier new, monospace">std::ma=
ke_unique()</font><font face=3D"arial, sans-serif">) could be specified to =
behave "as if" they called </font><font face=3D"courier new, monospace">std=
::construct()</font><font face=3D"arial, sans-serif">.</font></span></pre><=
/div></pre></div><div><font face=3D"arial, sans-serif"><span style=3D"line-=
height: 17px;">
</span></font></div><div><font face=3D"arial, sans-serif" size=3D"4"><span =
style=3D"line-height: 17px;">Conclusion</span></font></div><div>
</div><div><font face=3D"arial, sans-serif">Uniform initialization, introdu=
ced in C++11, is unfortunately not particularly at all uniform thanks to</f=
ont></div><div><font face=3D"courier new, monospace">std::initializer_list<=
/font><span style=3D"font-family: arial, sans-serif;"> constructors. (If no=
thing else, a type trait to detect when such a constructor is present</span=
></div><div><span style=3D"font-family: arial, sans-serif;">on a type would=
be beneficial by itself.) A </span><font face=3D"courier new, monospace">s=
td::construct()</font><span style=3D"font-family: arial, sans-serif;"> func=
tion which "does what you want"</span></div><div><span style=3D"font-family=
: arial, sans-serif;">would finally allow <b>truly</b> uniform initializati=
on for all C++ types, including simple aggregates. Let's do it.</span></div=
><div><span style=3D"font-family: arial, sans-serif;">
</span></div></pre></pre></pre>
</div>
</div>
</blockquote>
Hi,<br>
<br>
I would like to see this proposal in Oulu. I have a proposal for
generic make factories [1] that could use the proposed
std::constructor instead of using the using direct-initialization.<br>
My proposal is similar, but allows the user to customize the
creation of the instance. This is useful in particular when the
class has no constructor but has factories as future.<br>
<br>
I also prefer the alternative (2).<br>
<br>
I would add that in addition your proposal provides a function to
call a constructor which can be used is some algorithms.<br>
<br>
Best,<br>
Vicente<br>
<br>
<br>
<br>
[1]
<a class=3D"moz-txt-link-freetext" href=3D"https://github.com/viboes/std-ma=
ke/blob/master/doc/proposal/factories/p0338r0.md">https://github.com/viboes=
/std-make/blob/master/doc/proposal/factories/p0338r0.md</a><br>
</body>
</html>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/b35314f6-2cd5-4f90-c8de-a53849a2f495%=
40wanadoo.fr?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b35314f6-2cd5-4f90-c8de-a53849a2f495=
%40wanadoo.fr</a>.<br />
--------------38A9DAC464565FE1C9147451--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Thu, 26 May 2016 01:38:16 -0700 (PDT)
Raw View
------=_Part_7762_204492784.1464251896877
Content-Type: multipart/alternative;
boundary="----=_Part_7763_492553281.1464251896878"
------=_Part_7763_492553281.1464251896878
Content-Type: text/plain; charset=UTF-8
On Wednesday, May 25, 2016 at 5:42:57 PM UTC+1, Tristan Brindle wrote:
>
>
> tl;dr
>
> I'd like to propose a std::construct() function to make it easier to use
> aggregate types in generic
> code, along with a couple of supporting type traits.
>
[...]
> These problems stem from the fact that in generic code, one must make a
> choice of whether to use
>
> *direct-initialization* style T(args...) or *list-initialization* style T{args...} when constructing a new value.
>
> The former leads to the inability to use types without user-defined constructors, while the latter leads to
>
> unexpected behaviour with types that have a constructor taking a std::initializer_list, as the T{args...} form
>
> will always prefer such a constructor. This being the case, generic code (including all cases in the
>
> standard library, as far as I know) invariably opts for the T(args...) form.
>
>
> A Solution (1)
>
>
> Since std::is_constructible is specified to use the *direct-initialization* form, it would appear to be enough
>
> to specify that if std::constructible<T, Args...>::value == false, then the *list-initialization* form should be tried
>
> instead. However,this would lead to initializer_list constructors being called in situations where it may not be
>
> expected.
>
> [...]
> Another Solution (2)
>
>
> A slightly more complex alternative which avoids the above problem would be to add a new type trait,
>
>
> template <class T>
>
> struct has_initializer_list_constructor;
>
>
> which is std::true_type if T has any constructor taking an intializer_list.
>
>
>
3. Burn initializer_list with fire and ignore the existence of any type
that has mixed initializer_list/aggregate constructors. Always use the {}
syntax for initialization. Advocate the use of the seq<> wrapper discussed
the initializer_list thread.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/01703042-5362-4a55-9289-104611b97221%40isocpp.org.
------=_Part_7763_492553281.1464251896878
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, May 25, 2016 at 5:42:57 PM UTC+1, Tristan Br=
indle wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
br><div><font size=3D"4">tl;dr</font></div><div><br></div><div>I'd like=
to propose a <font face=3D"courier new, monospace">std::construct() </font=
>function to make it easier to use aggregate types in generic</div><div>cod=
e, along with a couple of supporting type traits.</div><font face=3D"arial,=
sans-serif"></font></div></blockquote><div>[...] <br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><font face=3D"arial, sans-se=
rif">These problems stem from the fact that in generic code, one must make =
a choice of whether to use </font><div><pre><pre><font face=3D"arial, sans-=
serif"><i>direct-initialization</i> style </font><font face=3D"courier new,=
monospace">T(args...) </font><font face=3D"arial, sans-serif">or <i>list-i=
nitialization</i> style </font><font face=3D"courier new, monospace">T{args=
....}</font><font face=3D"arial, sans-serif"> when constructing a new value.=
</font></pre><pre><font face=3D"arial, sans-serif">The former leads to the =
inability to </font><span style=3D"font-family:arial,sans-serif">use types =
without user-defined constructors, while the latter leads to</span></pre><p=
re><span style=3D"font-family:arial,sans-serif">unexpected behaviour with t=
ypes </span><span style=3D"font-family:arial,sans-serif">that have a constr=
uctor taking a </span><font face=3D"courier new, monospace">std::initialize=
r_list</font><span style=3D"font-family:arial,sans-serif">, as the </span><=
font face=3D"courier new, monospace">T{args...}</font><span style=3D"font-f=
amily:arial,sans-serif"> form</span></pre><pre><span style=3D"font-family:a=
rial,sans-serif">will always prefer such </span><span style=3D"font-family:=
arial,sans-serif">a constructor. This being the case, generic code (includi=
ng all cases in the=C2=A0</span></pre><pre><span style=3D"font-family:arial=
,sans-serif">standard library, as far as I know) invariably opts for the </=
span><font face=3D"courier new, monospace">T(args...)</font><span style=3D"=
font-family:arial,sans-serif"> form.</span></pre><pre><font face=3D"arial, =
sans-serif"><br></font></pre><pre><font face=3D"arial, sans-serif" size=3D"=
4">A Solution (1)</font></pre><pre><font face=3D"arial, sans-serif"><br></f=
ont></pre><pre><font face=3D"arial, sans-serif">Since </font><font face=3D"=
courier new, monospace">std::is_constructible</font><font face=3D"arial, sa=
ns-serif"> is specified to use the <i>direct-initialization</i> form, it wo=
uld appear to be enough</font></pre><pre><font face=3D"arial, sans-serif">t=
o specify that if </font><font face=3D"courier new, monospace">std::constru=
ctible<T, Args...>::value =3D=3D false</font><font face=3D"arial, san=
s-serif">, then the <i>list-initialization</i> form should be tried</font><=
/pre><pre><font face=3D"arial, sans-serif">instead. However,</font><span st=
yle=3D"font-family:arial,sans-serif">this would lead to </span><font face=
=3D"courier new, monospace">initializer_list</font><span style=3D"font-fami=
ly:arial,sans-serif"> constructors being called in situations where it may =
not be</span></pre><pre><span style=3D"font-family:arial,sans-serif">expect=
ed.</span></pre><font face=3D"arial, sans-serif" size=3D"4"></font></pre></=
div></div></blockquote><div>[...] <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 dir=3D"ltr"><div><pre><font face=3D"arial, sans-serif" s=
ize=3D"4">Another Solution (2)</font><pre><font face=3D"arial, sans-serif">=
<br></font></pre><pre><font face=3D"arial, sans-serif">A slightly more comp=
lex alternative which avoids the above problem would be to add a new type t=
rait,</font></pre><pre><br></pre><pre><pre> <span style=3D"color:#808000=
">template</span><span style=3D"color:#c0c0c0"> </span><span style=3D"color=
:#000000"><</span><span style=3D"color:#808000">class</span><span style=
=3D"color:#c0c0c0"> </span><span style=3D"color:#800080">T</span><span styl=
e=3D"color:#000000">></span></pre><pre><span style=3D"color:#808000"> =
struct</span><span style=3D"color:#c0c0c0"> </span><span style=3D"color:#8=
00080">has_initializer_list_<wbr>constructor</span><span style=3D"color:#00=
0000">;</span></pre><pre><span style=3D"color:#000000"><br></span></pre><pr=
e><font face=3D"arial, sans-serif">which is </font><font face=3D"courier ne=
w, monospace">std::true_type</font><font face=3D"arial, sans-serif"> if </f=
ont><font face=3D"courier new, monospace">T</font><font face=3D"arial, sans=
-serif"> has any constructor taking an </font><font face=3D"courier new, mo=
nospace">intializer_list</font><span style=3D"font-family:arial,sans-serif"=
>. </span></pre><br></pre></pre></div></div></blockquote><div><br>3. Burn i=
nitializer_list with fire and ignore the existence of any type that has mix=
ed initializer_list/aggregate constructors. Always use the {} syntax for in=
itialization. Advocate the use of the seq<> wrapper discussed the ini=
tializer_list thread.<br>=C2=A0</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/01703042-5362-4a55-9289-104611b97221%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/01703042-5362-4a55-9289-104611b97221=
%40isocpp.org</a>.<br />
------=_Part_7763_492553281.1464251896878--
------=_Part_7762_204492784.1464251896877--
.