Topic: Whatever happened to LWG 2089?


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 31 Dec 2016 08:47:29 -0800 (PST)
Raw View
------=_Part_3791_1264762424.1483202849923
Content-Type: multipart/alternative;
 boundary="----=_Part_3792_1770420111.1483202849924"

------=_Part_3792_1770420111.1483202849924
Content-Type: text/plain; charset=UTF-8

LWG 2089 <http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2089>
is a library issue about `emplace`-style functions not being able to
perform aggregate initialization. While it is expressed specifically for
`allocator::construct`, new C++ changes (the deprecation of
`allocator::construct`, `make_shared/unique`, the `in_place_t` constructors
for `any` et. al) would suggest that any appropriate fix be applied
elsewhere too.

The issue itself is still active. It has the status "EWG", due to wanting
to investigate whether Evolution would like to pursue a language-based
solution to such initialization issues (ie: asking if EWG is OK with the
library essentially creating a new form of initialization).

This was presented in N4462 at Lexana, apparently. The EWG issue, #185
<https://cplusplus.github.io/EWG/ewg-active.html#185>, is set to the status
"Ready", with the comment that EWG is fine with this being a library-based
solution. That was in mid-2015.

So... now what? The LWG issue seems to be waiting for EWG, which made their
decision back in 2015. And yet, nothing has gone anywhere. Is the issue
moving forward?

I bring this up in part because I think LWG 2089 is flawed. Or more to the
point, I would rather it be restricted specifically to aggregate
initialization.

Basically, the current solution presents the exact opposite of the classic
list-initialization problem: when constructors and `initializer_list`
constructors conflict. Consider a `vector<vector<int>>`. If you call
`emplace_back(5, 3, 2)`, you get an `initializer_list` constructor. If you
call `emplace_back(5, 3)`, you get a vector of 5 integers with the value 3.
As mentioned in 2089, you can work around that by explicitly asking for an
`initializer_list`: `emplace_back(initializer_list<int>{5, 3})`.

And since this works exactly the opposite of list-initialization, I think
people would not expect it. Or worse, they'll be bitten by this bug once
they hear that they can use `emplace` to provoke list-initialization.

I think it would be best that, if you want an `initializer_list`
constructor, you *always* have to spell it out. It makes it much more clear
to the reader what's going on. Further, if a user adds a new constructor to
the type that happens to match an `initializer_list` sequence, that won't
suddenly break someone's `emplace` code.

Note: I am aware of how painfully verbose `std::initializer_list<type>` is.
But frankly, that is a general problem in C++, one I believe we can solve.

Essentially, I say that LWG 2089 should be exclusively about adding
aggregate initialization support to indirect forms of initialization (my
term for all kinds of `emplace`-like behavior). It should be explicitly
restricted from invoking list-initialization for non-aggregates. Of course,
doing that in the library would require an `is_aggregate<T>` trait. But
quite frankly, we've needed that trait for some time now.

Basically, the fundamental conceit of list-initialization is the belief
that all you need in order to initialize an object is a list of values.
After years of using list-initialization, I think we've proven that this is
not true: that there really are different forms of initialization beyond
just the parameters, and that these forms have to be explicitly provided.
And we should not encode this false believe into indirect initialization
APIs.

--
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/1fe0f407-1a63-441f-a646-d098962afff2%40isocpp.org.

------=_Part_3792_1770420111.1483202849924
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/lwg=
-active.html#2089">LWG 2089</a> is a library issue about `emplace`-style fu=
nctions not being able to perform aggregate initialization. While it is exp=
ressed specifically for `allocator::construct`, new C++ changes (the deprec=
ation of `allocator::construct`, `make_shared/unique`, the `in_place_t` con=
structors for `any` et. al) would suggest that any appropriate fix be appli=
ed elsewhere too.<br><br>The issue itself is still active. It has the statu=
s &quot;EWG&quot;, due to wanting to investigate whether Evolution would li=
ke to pursue a language-based solution to such initialization issues (ie: a=
sking if EWG is OK with the library essentially creating a new form of init=
ialization).<br><br>This was presented in N4462 at Lexana, apparently. The =
<a href=3D"https://cplusplus.github.io/EWG/ewg-active.html#185">EWG issue, =
#185</a>, is set to the status &quot;Ready&quot;, with the comment that EWG=
 is fine with this being a library-based solution. That was in mid-2015.<br=
><br>So... now what? The LWG issue seems to be waiting for EWG, which made =
their decision back in 2015. And yet, nothing has gone anywhere. Is the iss=
ue moving forward?<br><br>I bring this up in part because I think LWG 2089 =
is flawed. Or more to the point, I would rather it be restricted specifical=
ly to aggregate initialization.<br><br>Basically, the current solution pres=
ents the exact opposite of the classic list-initialization problem: when co=
nstructors and `initializer_list` constructors conflict. Consider a `vector=
&lt;vector&lt;int&gt;&gt;`. If you call `emplace_back(5, 3, 2)`, you get an=
 `initializer_list` constructor. If you call `emplace_back(5, 3)`, you get =
a vector of 5 integers with the value 3. As mentioned in 2089, you can work=
 around that by explicitly asking for an `initializer_list`: `emplace_back(=
initializer_list&lt;int&gt;{5, 3})`.<br><br>And since this works exactly th=
e opposite of list-initialization, I think people would not expect it. Or w=
orse, they&#39;ll be bitten by this bug once they hear that they can use `e=
mplace` to provoke list-initialization.<br><br>I think it would be best tha=
t, if you want an `initializer_list` constructor, you <i>always</i> have to=
 spell it out. It makes it much more clear to the reader what&#39;s going o=
n. Further, if a user adds a new constructor to the type that happens to ma=
tch an `initializer_list` sequence, that won&#39;t suddenly break someone&#=
39;s `emplace` code.<br><br>Note: I am aware of how painfully verbose `std:=
:initializer_list&lt;type&gt;` is. But frankly, that is a general problem i=
n C++, one I believe we can solve.<br><br>Essentially, I say that LWG 2089 =
should be exclusively about adding aggregate initialization support to indi=
rect forms of initialization (my term for all kinds of `emplace`-like behav=
ior). It should be explicitly restricted from invoking list-initialization =
for non-aggregates. Of course, doing that in the library would require an `=
is_aggregate&lt;T&gt;` trait. But quite frankly, we&#39;ve needed that trai=
t for some time now.<br><br>Basically, the fundamental conceit of list-init=
ialization is the belief that all you need in order to initialize an object=
 is a list of values. After years of using list-initialization, I think we&=
#39;ve proven that this is not true: that there really are different forms =
of initialization beyond just the parameters, and that these forms have to =
be explicitly provided. And we should not encode this false believe into in=
direct initialization APIs.<br></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/1fe0f407-1a63-441f-a646-d098962afff2%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/1fe0f407-1a63-441f-a646-d098962afff2=
%40isocpp.org</a>.<br />

------=_Part_3792_1770420111.1483202849924--

------=_Part_3791_1264762424.1483202849923--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sat, 31 Dec 2016 19:06:03 +0200
Raw View
On 31 December 2016 at 18:47, Nicol Bolas <jmckesson@gmail.com> wrote:
> LWG 2089 is a library issue about `emplace`-style functions not being able
> to perform aggregate initialization. While it is expressed specifically for
> `allocator::construct`, new C++ changes (the deprecation of
> `allocator::construct`, `make_shared/unique`, the `in_place_t` constructors
> for `any` et. al) would suggest that any appropriate fix be applied
> elsewhere too.
>
> The issue itself is still active. It has the status "EWG", due to wanting to
> investigate whether Evolution would like to pursue a language-based solution
> to such initialization issues (ie: asking if EWG is OK with the library
> essentially creating a new form of initialization).
>
> This was presented in N4462 at Lexana, apparently. The EWG issue, #185, is
> set to the status "Ready", with the comment that EWG is fine with this being
> a library-based solution. That was in mid-2015.
>
> So... now what? The LWG issue seems to be waiting for EWG, which made their
> decision back in 2015. And yet, nothing has gone anywhere. Is the issue
> moving forward?

Well, first of all, "The notes in Lenexa say that Marshall & Jonathan
volunteered to write a paper on this".
Marshall and Jonathan have been far too busy with other things, so I'm
not expecting anything
in this area for C++17. Beyond that, the problem needs further work.

> I bring this up in part because I think LWG 2089 is flawed. Or more to the
> point, I would rather it be restricted specifically to aggregate
> initialization.

The general problem is that it's impossible for a wrapper to convey
initialization really-perfectly.
Currently, a wrapper like make_unique has to make a decision - whether
to paren-init or whether
to brace-init, because that still can make a difference. N4462
explores potential solutions, but
doesn't nail down any particular one.

> I think it would be best that, if you want an `initializer_list`
> constructor, you always have to spell it out. It makes it much more clear to

But that's not the problem. If you have an initializer_list
constructor, you can give an initializer_list
to a wrapper and it *can* forward it(*). But what the wrapper can't do
is know whether your
target type to be wrapped can or cannot be paren-initialized, or
whether that target type
*requires* brace-init. Like aggregates do.
(*) Well, ok, unicorn initialization and imperfect forwarding can't
know that your potential
braced-list is meant to be an initializer_list.

> Essentially, I say that LWG 2089 should be exclusively about adding
> aggregate initialization support to indirect forms of initialization (my
> term for all kinds of `emplace`-like behavior). It should be explicitly
> restricted from invoking list-initialization for non-aggregates. Of course,
> doing that in the library would require an `is_aggregate<T>` trait. But
> quite frankly, we've needed that trait for some time now.

We have? Where? Evidence, please? Note: I'm not outright claiming that
we couldn't
*use* such a trait in some cases. I'm asking what evidence supports such a trait
and makes it the *correct* solution to the problem space of LWG 2089 and N4462.

In order to make substantiated claims about any of it, I
(want/need/)demand to see
- an implementation of the solution, whatever it is
- some findings on what its impact on an existing testsuite is
- preferably some findings on what its impact on non-testsuite code is.

Prior to that, all talk is cheap. The reason why I, Marshall nor
Jonathan haven't tried to slam-dunk
anything towards LEWG yet is that we have none of the above.
Regardless of "who the f*** are you",
Marshall and Jonathan are stdlib maintainers, and wrt "who the f*** am
I", I wouldn't let any solution
in this problem space anywhere near C++ without doing the homework
mentioned above.
The reason being that the initialization rules, and library facilities
above, wrapping and accommodating
them were in a state of flux to the very end of standardizing C++11.
To change something in this
area *requires* care. We have existing users relying on the current
rules, sane or not (both the users
and the rules), and changing them requires rationale, motivation,
proof-of-concept and testing.

I am, Yours Most Sincerely,
Ville Voutilainen,
The Chair of The Evolution Working Group

--
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/CAFk2RUZ3QjaPpCSg5FV1_iZXLPWjq-b0Wi9-V7askEZ%3DvJ_%3Dmw%40mail.gmail.com.

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sat, 31 Dec 2016 20:07:00 +0200
Raw View
On 31 December 2016 at 19:06, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
>> Essentially, I say that LWG 2089 should be exclusively about adding
>> aggregate initialization support to indirect forms of initialization (my
>> term for all kinds of `emplace`-like behavior). It should be explicitly
>> restricted from invoking list-initialization for non-aggregates. Of course,
>> doing that in the library would require an `is_aggregate<T>` trait. But
>> quite frankly, we've needed that trait for some time now.
>
> We have? Where? Evidence, please? Note: I'm not outright claiming that
> we couldn't
> *use* such a trait in some cases. I'm asking what evidence supports such a trait
> and makes it the *correct* solution to the problem space of LWG 2089 and N4462.


Let me elaborate: which is the right question to ask:
- whether a type is an aggregate?
- whether a type can be initialized in a certain fashion?

In general, it seems better to be able to query whether a certain
expression is valid
for an object of a type, rather than what properties a (class) type
has. What motivates an is_aggregate
trait, rather than being able to query whether
aggregate(-like)-initialization is valid
for that type?

--
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/CAFk2RUZOe6Gmx9xaHurULCBYga%2Bnv3Fd8GZ6zq3iLCtiNDo5Cw%40mail.gmail.com.

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 31 Dec 2016 14:36:19 -0800 (PST)
Raw View
------=_Part_5101_1939478186.1483223779385
Content-Type: multipart/alternative;
 boundary="----=_Part_5102_556458594.1483223779386"

------=_Part_5102_556458594.1483223779386
Content-Type: text/plain; charset=UTF-8

On Saturday, December 31, 2016 at 12:06:05 PM UTC-5, Ville Voutilainen
wrote:
>
> On 31 December 2016 at 18:47, Nicol Bolas <jmck...@gmail.com> wrote:
> > LWG 2089 is a library issue about `emplace`-style functions not being
> able
> > to perform aggregate initialization. While it is expressed specifically
> for
> > `allocator::construct`, new C++ changes (the deprecation of
> > `allocator::construct`, `make_shared/unique`, the `in_place_t`
> constructors
> > for `any` et. al) would suggest that any appropriate fix be applied
> > elsewhere too.
> >
> > The issue itself is still active. It has the status "EWG", due to
> wanting to
> > investigate whether Evolution would like to pursue a language-based
> solution
> > to such initialization issues (ie: asking if EWG is OK with the library
> > essentially creating a new form of initialization).
> >
> > This was presented in N4462 at Lexana, apparently. The EWG issue, #185,
> is
> > set to the status "Ready", with the comment that EWG is fine with this
> being
> > a library-based solution. That was in mid-2015.
> >
> > So... now what? The LWG issue seems to be waiting for EWG, which made
> their
> > decision back in 2015. And yet, nothing has gone anywhere. Is the issue
> > moving forward?
>
> Well, first of all, "The notes in Lenexa say that Marshall & Jonathan
> volunteered to write a paper on this".
> Marshall and Jonathan have been far too busy with other things, so I'm
> not expecting anything
> in this area for C++17. Beyond that, the problem needs further work.
>
> > I bring this up in part because I think LWG 2089 is flawed. Or more to
> the
> > point, I would rather it be restricted specifically to aggregate
> > initialization.
>
> The general problem is that it's impossible for a wrapper to convey
> initialization really-perfectly.
>

"Impossible" is a very strong word ;)

Now to be fair, it *is* completely impossible to forward every form of
initialization perfectly... so long as you restrict the problem domain such
that parameters are only intended to be used to initialize the object.

But if we expand things a bit, if we allow the type of a parameter to
statically control the form of initialization:

template<typename T, typename ...Args>
T initialize(Args ...args)
{
    return T(std::forward<Args>(args)...);
}

template<typename T, typename ...Args>
T initialize(std::construct_init_t, Args ...args)
{
    return T(std::forward<Args>(args)...);
}

template<typename T, typename ...Args>
T initialize(std::list_init_t, Args ...args)
{
    return T{std::forward<Args>(args)...};
}

By using these control parameters, it is entirely possible to directly
control exactly how to initialize an object. It's not "perfect" (due to
narrowing and other issues), but it's as close as C++ can get to you
actually writing the initialization yourself.

Now, I'm not saying I want to see this standardized. I'd much rather use
the ad-hoc approach outlined in LWG 2089. But it should be something to
think about.

And maybe... we could do both. If the primary overload of `initialize`
there used LWG 2089's rules (or my expanded rule, below), but the typed
overloads did not, that would allow people to have a very usable default,
but still be able to choose what they wanted.

On Saturday, December 31, 2016 at 1:07:02 PM UTC-5, Ville Voutilainen wrote:
>
> On 31 December 2016 at 19:06, Ville Voutilainen
> <ville.vo...@gmail.com <javascript:void(0)>> wrote:
> >> Essentially, I say that LWG 2089 should be exclusively about adding
> >> aggregate initialization support to indirect forms of initialization
> (my
> >> term for all kinds of `emplace`-like behavior). It should be explicitly
> >> restricted from invoking list-initialization for non-aggregates. Of
> course,
> >> doing that in the library would require an `is_aggregate<T>` trait. But
> >> quite frankly, we've needed that trait for some time now.
> >
> > We have? Where? Evidence, please? Note: I'm not outright claiming that
> > we couldn't
> > *use* such a trait in some cases. I'm asking what evidence supports such
> a trait
> > and makes it the *correct* solution to the problem space of LWG 2089 and
> N4462.
>
>
> Let me elaborate: which is the right question to ask:
> - whether a type is an aggregate?
> - whether a type can be initialized in a certain fashion?
>
> In general, it seems better to be able to query whether a certain
> expression is valid
> for an object of a type, rather than what properties a (class) type
> has. What motivates an is_aggregate
> trait, rather than being able to query whether
> aggregate(-like)-initialization is valid
> for that type?
>

Well, asking `is_aggregate` alone is a non-starter:

struct Agg
{
    int i;
};

class Value
{
public:
    operator Agg() const {...}
};

vector<Agg> v;
v.emplace(Value());

This has a well-defined meaning right now: this will call `operator Agg` to
get an `Agg`, then copy that `Agg` into the `vector`. It does the
equivalent of `Agg(Value())`.

If we changed the initialization routine to use `is_aggregate` *by itself*,
then the meaning of this code changes. Since `Agg` is an aggregate, it
would use list-initialization: `Agg{Value()}`. [dcl.init.list]3.1 doesn't
apply, nor does 3.2. So 3.3 applies: performing aggregate initialization.
And that is ill-formed, since `Value` is not convertible to an `int`.
Therefore, the code is ill-formed.

I'm not suggesting we make a backwards-incompatible change ;)

My suggestion is to ask *both* questions:

template<typename T, typename ...Args>
auto initialize(Args &&...args)
{
    if constexpr(is_constructible_v<T, Args...>)
        return T(std::forward<Args>(args)...);
    else if constexpr(is_aggregate_v<T>)
        return T{std::forward<Args>(args)...};
    else
        static_assert(false, "Cannot initialize with parameters");
    end
}

So if it is constructible through the arguments, then it calls the
constructor. If it's not constructible, but the type is an aggregate, then
it will perform list-initialization, which will always invoke aggregate
initialization (since the type wasn't constructible via `args`,
[dcl.init.list]/3.1 cannot possibly apply. And 3.2 can't apply, since
`args` can't be a string literal). And if neither is true, then it cannot
be initialized with those parameters at all.

The idea is simply to do what LWG 2089's current resolution is, except that
it has these properties:

vector<vector<int>> v;
v.emplace_back(5, 3);    //Valid, like before.
v.emplace_back(5, 3, 2); //Still ill-formed, as it was before
v.emplace_back(std::initializer_list<int>{5, 3, 2}); //Perfectly fine

I will admit to this though: the only reason to have `is_aggregate` is for
cases like this: for choosing to use list-initialization only on types that
actually are aggregates, rather than depending on the vagaries of
[over.match.list]/1.1.

Indeed, the lack of such a trait is the only reason why I this version of
`initialize` *myself* ;)

--
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/b8da7f41-0289-4b7c-bda8-ae965169065b%40isocpp.org.

------=_Part_5102_556458594.1483223779386
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Saturday, December 31, 2016 at 12:06:05 PM UTC-5, Ville=
 Voutilainen wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 31 Decem=
ber 2016 at 18:47, Nicol Bolas &lt;<a target=3D"_blank" rel=3D"nofollow">jm=
ck...@gmail.com</a>&gt; wrote:
<br>&gt; LWG 2089 is a library issue about `emplace`-style functions not be=
ing able
<br>&gt; to perform aggregate initialization. While it is expressed specifi=
cally for
<br>&gt; `allocator::construct`, new C++ changes (the deprecation of
<br>&gt; `allocator::construct`, `make_shared/unique`, the `in_place_t` con=
structors
<br>&gt; for `any` et. al) would suggest that any appropriate fix be applie=
d
<br>&gt; elsewhere too.
<br>&gt;
<br>&gt; The issue itself is still active. It has the status &quot;EWG&quot=
;, due to wanting to
<br>&gt; investigate whether Evolution would like to pursue a language-base=
d solution
<br>&gt; to such initialization issues (ie: asking if EWG is OK with the li=
brary
<br>&gt; essentially creating a new form of initialization).
<br>&gt;
<br>&gt; This was presented in N4462 at Lexana, apparently. The EWG issue, =
#185, is
<br>&gt; set to the status &quot;Ready&quot;, with the comment that EWG is =
fine with this being
<br>&gt; a library-based solution. That was in mid-2015.
<br>&gt;
<br>&gt; So... now what? The LWG issue seems to be waiting for EWG, which m=
ade their
<br>&gt; decision back in 2015. And yet, nothing has gone anywhere. Is the =
issue
<br>&gt; moving forward?
<br>
<br>Well, first of all, &quot;The notes in Lenexa say that Marshall &amp; J=
onathan
<br>volunteered to write a paper on this&quot;.
<br>Marshall and Jonathan have been far too busy with other things, so I&#3=
9;m
<br>not expecting anything
<br>in this area for C++17. Beyond that, the problem needs further work.
<br>
<br>&gt; I bring this up in part because I think LWG 2089 is flawed. Or mor=
e to the
<br>&gt; point, I would rather it be restricted specifically to aggregate
<br>&gt; initialization.
<br>
<br>The general problem is that it&#39;s impossible for a wrapper to convey
<br>initialization really-perfectly.<br></blockquote><br>&quot;Impossible&q=
uot; is a very strong word ;)<br><br>Now
 to be fair, it <b>is</b> completely impossible to forward every form of=20
initialization perfectly... so long as you restrict the problem domain such=
 that parameters are only intended to be used to initialize the object.<br>=
<br>But if we expand things a bit, if we allow the type of a parameter to s=
tatically control the form of initialization:<br><br><div style=3D"backgrou=
nd-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-styl=
e: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettypri=
nt"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #008;" class=3D"styled-by-prettify">template</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">typename</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">typename</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">...</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Arg=
s</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>T initializ=
e</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><=
span style=3D"color: #606;" class=3D"styled-by-prettify">Args</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">...</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">args</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-=
by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> T</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">std</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">forward</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"=
color: #606;" class=3D"styled-by-prettify">Args</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">&gt;(</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">args</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">)...);</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br><br></span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">template</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">&lt;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">t=
ypename</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> T<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">typename</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: #606;=
" class=3D"styled-by-prettify">Args</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>T initialize</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">std</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
>construct_init_t</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #606;" class=3D"styled-by-prettify">Args</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">...</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">args</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> T</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">(</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">forward</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span st=
yle=3D"color: #606;" class=3D"styled-by-prettify">Args</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">&gt;(</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">args</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">)...);</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br><br></span><span style=3D"color: #008;" class=3D"styled-=
by-prettify">template</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">&lt;</span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">typename</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">typename</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">...</span><span style=3D"color: #6=
06;" class=3D"styled-by-prettify">Args</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>T initialize</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">std</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">list_init_t</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #606;" class=3D"styled-by-prettify">Args</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">...</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">args</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> T</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">{</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">forward</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span st=
yle=3D"color: #606;" class=3D"styled-by-prettify">Args</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">&gt;(</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">args</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">)...};</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span></div></code></div><br>By
 using these control parameters, it is entirely possible to directly=20
control exactly how to initialize an object. It&#39;s not &quot;perfect&quo=
t; (due to=20
narrowing and other issues), but it&#39;s as close as C++ can get to you ac=
tually writing the initialization yourself.<br><br>Now,
 I&#39;m not saying I want to see this standardized. I&#39;d much rather us=
e the=20
ad-hoc approach outlined in LWG 2089. But it should be something to=20
think about.<br><br>And maybe... we could do both. If the primary overload =
of `initialize` there used LWG 2089&#39;s rules (or my expanded rule, below=
), but the typed overloads did not, that would allow people to have a very =
usable default, but still be able to choose what they wanted.<br><br>On Sat=
urday, December 31, 2016 at 1:07:02 PM UTC-5, Ville Voutilainen wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;">On 31 December 2016 at 19:06, Ville=
 Voutilainen
<br>&lt;<a href=3D"javascript:void(0)" target=3D"_blank" gdf-obfuscated-mai=
lto=3D"8wBSqjqSCgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;javas=
cript:&#39;;return true;" onclick=3D"this.href=3D&#39;javascript:&#39;;retu=
rn true;">ville.vo...@gmail.com</a>&gt; wrote:
<br>&gt;&gt; Essentially, I say that LWG 2089 should be exclusively about a=
dding
<br>&gt;&gt; aggregate initialization support to indirect forms of initiali=
zation (my
<br>&gt;&gt; term for all kinds of `emplace`-like behavior). It should be e=
xplicitly
<br>&gt;&gt; restricted from invoking list-initialization for non-aggregate=
s. Of course,
<br>&gt;&gt; doing that in the library would require an `is_aggregate&lt;T&=
gt;` trait. But
<br>&gt;&gt; quite frankly, we&#39;ve needed that trait for some time now.
<br>&gt;
<br>&gt; We have? Where? Evidence, please? Note: I&#39;m not outright claim=
ing that
<br>&gt; we couldn&#39;t
<br>&gt; *use* such a trait in some cases. I&#39;m asking what evidence sup=
ports such a trait
<br>&gt; and makes it the *correct* solution to the problem space of LWG 20=
89 and N4462.
<br>
<br>
<br>Let me elaborate: which is the right question to ask:
<br>- whether a type is an aggregate?
<br>- whether a type can be initialized in a certain fashion?
<br>
<br>In general, it seems better to be able to query whether a certain
<br>expression is valid
<br>for an object of a type, rather than what properties a (class) type
<br>has. What motivates an is_aggregate
<br>trait, rather than being able to query whether
<br>aggregate(-like)-<wbr>initialization is valid
<br>for that type?
<br></blockquote><div><br>Well, asking `is_aggregate` alone is a non-starte=
r:<br><br><div style=3D"background-color: rgb(250, 250, 250); border-color:=
 rgb(187, 187, 187); border-style: solid; border-width: 1px; overflow-wrap:=
 break-word;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=
=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">struct</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Agg</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> i</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br><br></span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">class</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Val=
ue</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">public</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">operator</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;=
" class=3D"styled-by-prettify">Agg</span><span style=3D"color: #660;" class=
=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">const</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{...}</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">};</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br><br>vector</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Agg</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">&gt;</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</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
(</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Value</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">());</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></c=
ode></div><br>This has a well-defined meaning right now: this will call `op=
erator Agg` to get an `Agg`, then copy that `Agg` into the `vector`. It doe=
s the equivalent of `Agg(Value())`.<br><br>If we changed the initialization=
 routine to use `is_aggregate` <i>by itself</i>, then the meaning of this c=
ode changes. Since `Agg` is an aggregate, it would use list-initialization:=
 `Agg{Value()}`. [dcl.init.list]3.1 doesn&#39;t apply, nor does 3.2. So 3.3=
 applies: performing aggregate initialization. And that is ill-formed, sinc=
e `Value` is not convertible to an `int`. Therefore, the code is ill-formed=
..<br><br>I&#39;m not suggesting we make a backwards-incompatible change ;)<=
br><br>My suggestion is to ask <i>both</i> questions:<br><br><div style=3D"=
background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); bor=
der-style: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"p=
rettyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span=
 style=3D"color: #008;" class=3D"styled-by-prettify">template</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">typename</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"colo=
r: #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">typename</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">...</span><span style=3D"color: #606;" class=3D"styled-by-prettif=
y">Args</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> initialize</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Args</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">&amp;&amp;...</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">args</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-=
by-prettify">if</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">cons=
texpr</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">is_constructib=
le_v</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">T</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">Args</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">...&gt;)</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">return</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">std</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">forward</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">&lt;</span><span style=3D"color: #606;" class=3D"styled-by-pre=
ttify">Args</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&gt;(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">args=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)...);</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=
=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">else</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">if</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">constexpr</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">is_aggregate_v</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">&gt;)</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">return</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> T</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">std</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
forward</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt=
;</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Args</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;(</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">args</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">)...};</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">else</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">sta=
tic_assert</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">false</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: #080;" class=3D"styled-by-prettify">&quot;Cannot initialize with par=
ameters&quot;</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">end</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><=
/div></code></div><br>So if it is constructible through the arguments, then=
 it calls the constructor. If it&#39;s not constructible, but the type is a=
n aggregate, then it will perform list-initialization, which will always in=
voke aggregate initialization (since the type wasn&#39;t constructible via =
`args`, [dcl.init.list]/3.1 cannot possibly apply. And 3.2 can&#39;t apply,=
 since `args` can&#39;t be a string literal). And if neither is true, then =
it cannot be initialized with those parameters at all.<br><br>The idea is s=
imply to do what LWG 2089&#39;s current resolution is, except that it has t=
hese properties:<br><br><div style=3D"background-color: rgb(250, 250, 250);=
 border-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; =
overflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyprin=
t"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">vector</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">vector</span><span style=3D"color: #080;" class=3D"styled-by-prettify=
">&lt;int&gt;</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> v<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>v</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">emplace_back</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #0=
66;" class=3D"styled-by-prettify">5</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: #066;" class=3D"styled-by-pre=
ttify">3</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =C2=A0 =
=C2=A0</span><span style=3D"color: #800;" class=3D"styled-by-prettify">//Va=
lid, like before.</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>v</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">emplace=
_back</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span style=3D"color: #066;" class=3D"styled-by-prettify">5</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #0=
66;" class=3D"styled-by-prettify">3</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: #066;" class=3D"styled-by-pre=
ttify">2</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #800;" class=3D"styled-by-prettify">//Still ill-formed,=
 as it was before</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>v</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">emplace=
_back</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">std</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">initializer_list</span><span=
 style=3D"color: #080;" class=3D"styled-by-prettify">&lt;int&gt;</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #066;" class=3D"styled-by-prettify">5</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"=
styled-by-prettify">3</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">2</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">});</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #800;" class=3D"styled-by-prettify">//Perfectly fine</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></code></=
div><br>I will admit to this though: the only reason to have `is_aggregate`=
 is for cases like this: for choosing to use list-initialization only on ty=
pes that actually are aggregates, rather than depending on the vagaries of =
[over.match.list]/1.1.<br><br>Indeed, the lack of such a trait is the only =
reason why I this version of `initialize` <i>myself</i> ;)<br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/b8da7f41-0289-4b7c-bda8-ae965169065b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b8da7f41-0289-4b7c-bda8-ae965169065b=
%40isocpp.org</a>.<br />

------=_Part_5102_556458594.1483223779386--

------=_Part_5101_1939478186.1483223779385--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sun, 1 Jan 2017 02:01:56 +0200
Raw View
On 1 January 2017 at 00:36, Nicol Bolas <jmckesson@gmail.com> wrote:
>> The general problem is that it's impossible for a wrapper to convey
>> initialization really-perfectly.
>
>
> "Impossible" is a very strong word ;)

Right, I meant as far as the current language allows, and I'm fully
aware that the language
can be changed. :)

> But if we expand things a bit, if we allow the type of a parameter to
> statically control the form of initialization:
>
> template<typename T, typename ...Args>
> T initialize(Args ...args)
> {
>     return T(std::forward<Args>(args)...);
> }
>
> template<typename T, typename ...Args>
> T initialize(std::construct_init_t, Args ...args)
> {
>     return T(std::forward<Args>(args)...);
> }
>
> template<typename T, typename ...Args>
> T initialize(std::list_init_t, Args ...args)
> {
>     return T{std::forward<Args>(args)...};
> }

Yeah, such ideas have been floated around occasionally. Such
approaches might even eventually
end up appearing as library tools, who knows. To what extent existing
rules can be changed or
bent is another matter, as I'm sure you understand.

> Now, I'm not saying I want to see this standardized. I'd much rather use the
> ad-hoc approach outlined in LWG 2089. But it should be something to think
> about.

Yep, duly noted, I think the interested parties are somewhat aware of
such ideas.

>> Let me elaborate: which is the right question to ask:
>> - whether a type is an aggregate?
> Well, asking `is_aggregate` alone is a non-starter:
>
> struct Agg
> {
>     int i;
> };
>
> class Value
> {
> public:
>     operator Agg() const {...}
> };
>
> vector<Agg> v;
> v.emplace(Value());
>
> This has a well-defined meaning right now: this will call `operator Agg` to
> get an `Agg`, then copy that `Agg` into the `vector`. It does the equivalent
> of `Agg(Value())`.
>
> If we changed the initialization routine to use `is_aggregate` by itself,
> then the meaning of this code changes. Since `Agg` is an aggregate, it would
> use list-initialization: `Agg{Value()}`. [dcl.init.list]3.1 doesn't apply,
> nor does 3.2. So 3.3 applies: performing aggregate initialization. And that
> is ill-formed, since `Value` is not convertible to an `int`. Therefore, the
> code is ill-formed.
>
> I'm not suggesting we make a backwards-incompatible change ;)

Well, +1. :) As much as some of us would like to change/tweak the
C++11 rules, the horses and the cows
are far in the field, and calling them home is.. ..challenging. :)

> My suggestion is to ask both questions:
>
> template<typename T, typename ...Args>
> auto initialize(Args &&...args)
> {
>     if constexpr(is_constructible_v<T, Args...>)
>         return T(std::forward<Args>(args)...);
>     else if constexpr(is_aggregate_v<T>)
>         return T{std::forward<Args>(args)...};
>     else
>         static_assert(false, "Cannot initialize with parameters");
>     end
> }
>
> So if it is constructible through the arguments, then it calls the
> constructor. If it's not constructible, but the type is an aggregate, then
> it will perform list-initialization, which will always invoke aggregate
> initialization (since the type wasn't constructible via `args`,
> [dcl.init.list]/3.1 cannot possibly apply. And 3.2 can't apply, since `args`
> can't be a string literal). And if neither is true, then it cannot be
> initialized with those parameters at all.

That approach is promising. In case Marshall, Jonathan and I manage to
forget any of this,
please do keep tabs on the follow-ups.

--
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/CAFk2RUZYLZfM8g%2Bim4OYkAa73NF4jpXvWfJ7u_6YSezs_ZhyAQ%40mail.gmail.com.

.


Author: Tony V E <tvaneerd@gmail.com>
Date: Sun, 01 Jan 2017 01:25:32 -0500
Raw View
Maybe we just need to allow functions to be called with {} as well as () an=
d overloaded on bracket type. So initialize(a,b,c) vs initialize{a,b,c}.

:-)


Sent=C2=A0from=C2=A0my=C2=A0BlackBerry=C2=A0portable=C2=A0Babbage=C2=A0Devi=
ce
=C2=A0 Original Message =C2=A0
From: Ville Voutilainen
Sent: Saturday, December 31, 2016 7:01 PM
To: ISO C++ Standard - Future Proposals
Reply To: std-proposals@isocpp.org
Subject: Re: [std-proposals] Whatever happened to LWG 2089?

On 1 January 2017 at 00:36, Nicol Bolas <jmckesson@gmail.com> wrote:
>> The general problem is that it's impossible for a wrapper to convey
>> initialization really-perfectly.
>
>
> "Impossible" is a very strong word ;)

Right, I meant as far as the current language allows, and I'm fully
aware that the language
can be changed. :)

> But if we expand things a bit, if we allow the type of a parameter to
> statically control the form of initialization:
>
> template<typename T, typename ...Args>
> T initialize(Args ...args)
> {
> return T(std::forward<Args>(args)...);
> }
>
> template<typename T, typename ...Args>
> T initialize(std::construct_init_t, Args ...args)
> {
> return T(std::forward<Args>(args)...);
> }
>
> template<typename T, typename ...Args>
> T initialize(std::list_init_t, Args ...args)
> {
> return T{std::forward<Args>(args)...};
> }

Yeah, such ideas have been floated around occasionally. Such
approaches might even eventually
end up appearing as library tools, who knows. To what extent existing
rules can be changed or
bent is another matter, as I'm sure you understand.

> Now, I'm not saying I want to see this standardized. I'd much rather use =
the
> ad-hoc approach outlined in LWG 2089. But it should be something to think
> about.

Yep, duly noted, I think the interested parties are somewhat aware of
such ideas.

>> Let me elaborate: which is the right question to ask:
>> - whether a type is an aggregate?
> Well, asking `is_aggregate` alone is a non-starter:
>
> struct Agg
> {
> int i;
> };
>
> class Value
> {
> public:
> operator Agg() const {...}
> };
>
> vector<Agg> v;
> v.emplace(Value());
>
> This has a well-defined meaning right now: this will call `operator Agg` =
to
> get an `Agg`, then copy that `Agg` into the `vector`. It does the equival=
ent
> of `Agg(Value())`.
>
> If we changed the initialization routine to use `is_aggregate` by itself,
> then the meaning of this code changes. Since `Agg` is an aggregate, it wo=
uld
> use list-initialization: `Agg{Value()}`. [dcl.init.list]3.1 doesn't apply=
,
> nor does 3.2. So 3.3 applies: performing aggregate initialization. And th=
at
> is ill-formed, since `Value` is not convertible to an `int`. Therefore, t=
he
> code is ill-formed.
>
> I'm not suggesting we make a backwards-incompatible change ;)

Well, +1. :) As much as some of us would like to change/tweak the
C++11 rules, the horses and the cows
are far in the field, and calling them home is.. ..challenging. :)

> My suggestion is to ask both questions:
>
> template<typename T, typename ...Args>
> auto initialize(Args &&...args)
> {
> if constexpr(is_constructible_v<T, Args...>)
> return T(std::forward<Args>(args)...);
> else if constexpr(is_aggregate_v<T>)
> return T{std::forward<Args>(args)...};
> else
> static_assert(false, "Cannot initialize with parameters");
> end
> }
>
> So if it is constructible through the arguments, then it calls the
> constructor. If it's not constructible, but the type is an aggregate, the=
n
> it will perform list-initialization, which will always invoke aggregate
> initialization (since the type wasn't constructible via `args`,
> [dcl.init.list]/3.1 cannot possibly apply. And 3.2 can't apply, since `ar=
gs`
> can't be a string literal). And if neither is true, then it cannot be
> initialized with those parameters at all.

That approach is promising. In case Marshall, Jonathan and I manage to
forget any of this,
please do keep tabs on the follow-ups.

--=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/CAFk2RUZYLZfM8g%2Bim4OYkAa73NF4jpXvWfJ7u_6YSezs_=
ZhyAQ%40mail.gmail.com.

--=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/20170101062532.4898896.16467.22061%40gmail.com.

.