In following program, struct C
has two constructors : one from std::initializer_list<A>
and the other from std::initializer_list<B>
. Then an object of the struct is created with C{{1}}
:
#include <initializer_list>
struct A {
int i;
};
struct B {
constexpr explicit B(int) {}
};
struct C {
int v;
constexpr C(std::initializer_list<A>) : v(1) {}
constexpr C(std::initializer_list<B>) : v(2) {}
};
static_assert( C{{1}}.v == 1 );
Since only aggregate A
can be implicitly constructed from int
, one could expect that C(std::initializer_list<A>)
is preferred and the program succeeds. And indeed it does in Clang.
However GCC complains:
error: call of overloaded 'C(<brace-enclosed initializer list>)' is ambiguous
note: candidate: 'constexpr C::C(std::initializer_list<B>)'
note: candidate: 'constexpr C::C(std::initializer_list<A>)'
and so does MSVC:
error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'C'
note: No constructor could take the source type, or constructor overload resolution was ambiguous
Demo: https://gcc.godbolt.org/z/joz91q4ed
Which compiler is correct here?
B::B(int)
will keep ambiguity, but now all compilers selectA
: gcc.godbolt.org/z/3n63nTfrW – Copyhold