[cfe-dev] [bug?] list-initialization failures in a return statement
Richard Smith
richard at metafoo.co.uk
Thu Aug 21 18:47:57 PDT 2014
On Thu, Aug 21, 2014 at 5:26 PM, Jim Porter <jvp4846 at g.rit.edu> wrote:
> On 8/21/2014 4:00 PM, Richard Smith wrote:
>
>> On Mon, Aug 18, 2014 at 8:59 AM, Jim Porter <jvp4846 at g.rit.edu
>> <mailto:jvp4846 at g.rit.edu>> wrote:
>>
>> I've found what I think are a couple of bugs in how clang (3.4)
>> list-initializes objects in a return statement. It probably applies
>> to any copy-list-initialization context, but I haven't tested all
>> the possibilities. I'm posting this here instead of just filing a
>> bug because I wanted to get some feedback on whether I'm correct
>> about this or not.
>>
>> --------------------
>>
>> First, I think clang is incorrectly failing on the explicit default
>> constructor in this sample:
>>
>> struct foo {
>> explicit foo() {}
>> };
>>
>> foo make_foo() {
>> return {};
>> }
>>
>> int main() {
>> auto f = make_foo();
>> return 0;
>> }
>>
>> clang tells me "chosen constructor is explicit in
>> copy-initialization", but according to 8.5.4p3, make_foo should be
>> value-initializing foo:
>>
>> If the initializer list has no elements and T is a class type with
>> a
>> default constructor, the object is value-initialized.
>>
>>
>> OK, but value-initialization defers to default-initialization here, and
>> default-initialization performs overload resolution to select the
>> default constructor. This -- presumably -- uses 13.3.1.7 to select the
>> constructor:
>>
>> "When objects of non-aggregate class type T are list-initialized
>> (8.5.4), overload resolution selects the constructor in two phases:
>> -- [choose from initializer-list constructors]
>> -- [try all constructors]
>> If the initializer list has no elements and T has a default constructor,
>> the first phase is omitted. In copy-list-initialization, if an explicit
>> constructor is chosen, the initialization is ill-formed."
>>
>> Since we're in copy-list-initialization, T has a default constructor,
>> and the list has no elements, we try all constructors. Since we pick an
>> explicit constructor, the program is ill-formed.
>>
>
> Hmm. Does this mean it's impossible to write a function that constructs an
> arbitrary DefaultConstructible object? I had hoped to do something like
>
> template<typename T>
> T make() {
> return {};
> }
>
> 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...
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.
Here's a dumb workaround:
template<typename T> struct DirectInit {
T value{};
operator T&() & { return value; }
operator T&&() && { return value; }
// ...
};
template<typename T> DirectInit<T> make() { return {}; }
... but I'm somewhat wondering why you would have an explicit default
constructor in the first place.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20140821/8ef16972/attachment.html>
More information about the cfe-dev
mailing list