2

Why do seemingly all compilers reject the following program? (https://godbolt.org/z/EK8zW34nY)

struct A
{
    explicit A() {}
};

int main()
{
    A a = {};
}

a should be value-initialized per [dcl.init.list]/3.5 from what I can tell and that should in turn select a constructor as if to default-initialize a Default-initialization does not exclude explicit constructors.


This is a follow-up from a discussion with another user in another question:

Would one apply [over.match.list], which I do not think should apply here, then it would fail because of "In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed.".

When modifying the program to

struct A
{
    explicit A() {}

    template<typename = void>
    A() {}
};

int main()
{
    A a = {};
}

then GCC and Clang still reject it with error messages hinting that they consider it that way, while EDG and MSVC accept, choosing the templated constructor as if there was "copy-default-initialization" which excludes explicit constructors completely. (https://godbolt.org/z/xbzjhYYhM)

0

2 Answers 2

5

When you do

A a = {};

You are using copy-list-initialization which brings in [over.match.ctor] which states:

When objects of class type are direct-initialized, copy-initialized from an expression of the same or a derived class type ([dcl.init]), or default-initialized, overload resolution selects the constructor. For direct-initialization or default-initialization (including default-initialization in the context of copy-list-initialization), the candidate functions are all the constructors of the class of the object being initialized. Otherwise, the candidate functions are all the converting constructors ([class.conv.ctor]) of that class. The argument list is the expression-list or assignment-expression of the initializer. For default-initialization in the context of copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed.

And since the object is not being initialized from an expression of the same or derived type the second half applies and last part of the last sentence makes the code ill formed.


This makes sense since {} isn't an A, its an implicit object creator and you cant make an implicit object from a type that has an explicit default constructor.

Sign up to request clarification or add additional context in comments.

2 Comments

@user17732522 Updated with what I believe is the correct section.
Ah, I noticed that I overlooked the current wording at the end just when you edited your question as well.
2

It turned out to be an issue of reading comprehension. The end of [over.match.ctor] after CWG 2856 says:

For default-initialization in the context of copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed.

Thereby GCC and Clang are behaving correctly, even though [over.match.ctor] applies instead of [over.match.list].

MSVC and EDG probably haven't implemented the defect report yet. Before this defect report the wording of [over.match.ctor] excluded explicit constructors for direct-initialization in the context of copy-list-initialization.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.