C++ Logo

std-discussion

Advanced search

Re: inheriting initializer_list constructor fails with empty list

From: Russell Shaw <rjshaw_at_[hidden]>
Date: Tue, 28 May 2024 01:05:21 +1000
On 28/5/24 00:16, Svetlin Totev via Std-Discussion wrote:
> C++ allows "inheriting" constructors with a special rule for using-declarations.
> It also has a special rule for constructors that take std::initializer_list
> which changes the syntax for the constructor call.
>
> These two rules don't work consistently together. The special syntax for
> constructors with std::initializer_list doesn't get inherited in all cases. In
> the example below the line "B b1 {};" fails to compile because it tries to call
> A() instead of A{}. Technically the constructors are inherited correctly. It's
> the special syntax for initializer lists that doesn't get inherited in the edge
> case of empty {} brackets. But it is inherited in all other cases.
>
> I'm not entirely sure if this is a language issue or a compiler one as I can't
> fully comprehend the C++ standard but both gcc and clang would fail to compile
> this example code and give the same reason.
>
> This language has too many special cases. Let's not have another one. Currently,
> the struct C in the example code is a working workaround for the issue.
...
>
> Bb1 {}; // calls A() instead of A{} so it fails____
>
> Bb2 {1, 2, 3}; // ok____

---------------------------------------------
ISO/IEC 14882:2020(E)
9.4.5 List-initialization [dcl.init.list]

(3.5) — Otherwise, if the initializer list has no elements and T is a class type
with a default constructor, the object is value-initialized.
---------------------------------------------

‘B::B()’ is implicitly deleted because the default definition would be
ill-formed. There is no A::A() default constructor. That's my interpretation,
anyway.

g++ -DHAVE_CONFIG_H -I. -Wall -Wno-unused -Wno-unused-function
-Wno-unused-label -Wno-unused-parameter -Wno-unused-value -Wno-parentheses
-std=c++20 -Wno-address -Wpedantic -g -O0 -MT main.o -MD -
MP -MF .deps/main.Tpo -c -o main.o main.cpp
main.cpp: In function ‘int main()’:
main.cpp:111:11: error: use of deleted function ‘B::B()’
   111 | B b1 {}; // calls A() instead of A{} so it fails
       | ^
main.cpp:85:8: note: ‘B::B()’ is implicitly deleted because the default
definition would be ill-formed:
    85 | struct B : A {
       | ^
main.cpp:85:8: error: no matching function for call to ‘A::A()’
main.cpp:82:5: note: candidate: ‘A::A(std::initializer_list<int>)’
    82 | A(std::initializer_list<int> il) {};
       | ^
main.cpp:82:5: note: candidate expects 1 argument, 0 provided
main.cpp:81:8: note: candidate: ‘constexpr A::A(const A&)’
    81 | struct A {
       | ^
main.cpp:81:8: note: candidate expects 1 argument, 0 provided
main.cpp:81:8: note: candidate: ‘constexpr A::A(A&&)’
main.cpp:81:8: note: candidate expects 1 argument, 0 provided
make[1]: *** [Makefile:430: main.o] Error 1
make[1]: Leaving directory '/home/russell/AAProjs/GNU/bugs/g++'
make: *** [Makefile:315: all] Error 2
"main.cpp" 127 lines --0%--
(9 of 28): error: use of deleted function ‘B::B()’

Received on 2024-05-27 15:05:28