<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Aug 21, 2014 at 5:26 PM, Jim Porter <span dir="ltr"><<a href="mailto:jvp4846@g.rit.edu" target="_blank">jvp4846@g.rit.edu</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="">On 8/21/2014 4:00 PM, Richard Smith wrote:<br>
</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="">
On Mon, Aug 18, 2014 at 8:59 AM, Jim Porter <<a href="mailto:jvp4846@g.rit.edu" target="_blank">jvp4846@g.rit.edu</a><br></div><div><div class="h5">
<mailto:<a href="mailto:jvp4846@g.rit.edu" target="_blank">jvp4846@g.rit.edu</a>>> wrote:<br>
<br>
I've found what I think are a couple of bugs in how clang (3.4)<br>
list-initializes objects in a return statement. It probably applies<br>
to any copy-list-initialization context, but I haven't tested all<br>
the possibilities. I'm posting this here instead of just filing a<br>
bug because I wanted to get some feedback on whether I'm correct<br>
about this or not.<br>
<br>
--------------------<br>
<br>
First, I think clang is incorrectly failing on the explicit default<br>
constructor in this sample:<br>
<br>
struct foo {<br>
explicit foo() {}<br>
};<br>
<br>
foo make_foo() {<br>
return {};<br>
}<br>
<br>
int main() {<br>
auto f = make_foo();<br>
return 0;<br>
}<br>
<br>
clang tells me "chosen constructor is explicit in<br>
copy-initialization", but according to 8.5.4p3, make_foo should be<br>
value-initializing foo:<br>
<br>
If the initializer list has no elements and T is a class type with a<br>
default constructor, the object is value-initialized.<br>
<br>
<br>
OK, but value-initialization defers to default-initialization here, and<br>
default-initialization performs overload resolution to select the<br>
default constructor. This -- presumably -- uses 13.3.1.7 to select the<br>
constructor:<br>
<br>
"When objects of non-aggregate class type T are list-initialized<br>
(8.5.4), overload resolution selects the constructor in two phases:<br>
-- [choose from initializer-list constructors]<br>
-- [try all constructors]<br>
If the initializer list has no elements and T has a default constructor,<br>
the first phase is omitted. In copy-list-initialization, if an explicit<br>
constructor is chosen, the initialization is ill-formed."<br>
<br>
Since we're in copy-list-initialization, T has a default constructor,<br>
and the list has no elements, we try all constructors. Since we pick an<br>
explicit constructor, the program is ill-formed.<br>
</div></div></blockquote>
<br>
Hmm. Does this mean it's impossible to write a function that constructs an arbitrary DefaultConstructible object? I had hoped to do something like<br>
<br>
template<typename T><br>
T make() {<br>
return {};<br>
}<br>
<br>
so that I could construct non-movable objects, but I guess that won't work for objects with explicit default constructors. It seems like clang is indeed doing the right thing, so perhaps this is an issue to bring up with the standards committee...</blockquote>
<div><br></div><div>If you'll excuse me making up terms, DefaultConstructible only requires that direct-default-initialization is valid, not that copy-default-list-initialization is valid. That's probably the bug in the standard; your type should probably not be considered to be DefaultConstructible.</div>
<div><br></div><div>Here's a dumb workaround:</div><div><br></div><div> template<typename T> struct DirectInit {</div><div> T value{};</div><div> operator T&() & { return value; }</div><div> operator T&&() && { return value; }</div>
<div> // ...</div><div> };</div><div> template<typename T> DirectInit<T> make() { return {}; }</div><div><br></div><div>... but I'm somewhat wondering why you would have an explicit default constructor in the first place.</div>
</div></div></div>