C++ Logo

std-discussion

Advanced search

Re: inheriting initializer_list constructor fails with empty list

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Wed, 29 May 2024 06:49:11 +0100
On 28 May 2024 20:33:54 BST, Svetlin Totev via Std-Discussion <std-discussion_at_[hidden]> wrote:
>Ok so I finally understand the reasons why the error occurs:
>B "doesn't have user-declared constructors" so the compiler has to create a
>default constructor, but it becomes ill-formed because A doesn't have one.
>
>11.4.5.2 Default constructors [class.default.ctor]
>1. ... If there is no user-declared constructor for class X, a non-explicit
>constructor having no parameters is implicitly declared as defaulted
>([dcl.fct.def])...
>
>So this would mean that the using-declaration "using A::A;" is not a
>declaration of constructors. And yet it behaves exactly as user-declared
>constructors except when asked the specific question: "are there any
>user-declared constructors".
>
>9.9 The using declaration [namespace.udecl]
>13 Constructors that are named by a using-declaration are treated as though
>they were constructors of the derived class when looking up the
>constructors of the derived class ([class.qual]) or forming a set of
>overload candidates ([over.match.ctor], [over.match.copy],
>[over.match.list]).
>
>So I suppose the wording of the rule about inheriting constructors only
>talks about how they should be treated for constructor lookup and doesn't
>explicitly call this a declaration of constructors word-for-word. So even
>though it is a declaration of constructors explicitly done by the user,
>there are no user-declared constructors.
>
>This is an absurd and very counterproductive interpretation of the rules
>that just adds yet another trap in the language and ruins the main use case
>of inheriting constructors: to make the derived class have the same
>constructors as the base class.
>I'm sorry to say this but this language is unsalvageable. I spend 10x more
>time fighting it than using it...

I think your assessment is right. This might fly as a defect, so please report it as such at https://github.com/cplusplus/CWG/issues . In the worst case you will be told to write a paper.

It is salvageable.

>
>P.S.:
>
>And the reason the initializer_list constructor isn't picked:
>
>12.2.2.8 Initialization by list-initialization [over.match.list]
>(1.1) If the initializer list is not empty or T has no default constructor,
>overload resolution is first performed where the candidate functions are
>the initializer-list constructors ([dcl.init.list]) of the class T and the
>argument list consists of the initializer list as a single argument.
>
>So B now has an ill-formed default constructor which has higher priority
>than the initializer_list one.
>
>On Tue, May 28, 2024 at 4:59 PM M.P. via Std-Discussion <
>std-discussion_at_[hidden]> wrote:
>
>> > B doesn't have a default constructor, just like A doesn't have one
>>
>> B has an implicitly-declared default constructor, see
>> [class.default.ctor]/1.
>>
>> Adding a user-declared constructor to B suppresses the implicit
>> declaration:
>>
>> #include <initializer_list>
>>
>> struct A { A(std::initializer_list<int>); };
>> struct B : A {
>> using A::A;
>> B(void*);
>> };
>>
>> A a {}; // ok
>> B b {}; // ok
>>
>>
>> --
>> Std-Discussion mailing list
>> Std-Discussion_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>

Received on 2024-05-29 05:49:18