Copy-initialisation and explicit constructor - compiler discrepancy
c++, constructor, gcc, visual-c++
Solution
Stolen from this answer, the standard says:
12.3 Conversions [class.conv]
4 At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.
You're trying to perform two in one step, `S` which needs to be converted for `B`'s constructor that accepts an `A`, and then another for `A`'s constructor that accepts an `S`. The solution is to first cast `S` into an `A`:
B b1 = static_cast<A>(s);
Problem
I've discovered a discrepancy between the Microsoft Visual C++ compiler, and gcc-4.8.1 (as provided by ideone.com). Consider the following SSCCE: ``` struct S { int x; }; class A { public: int x; A(const S& s) : x(s.x) {} }; class B { int x, y; public: template <typename T> explicit B(const T& t) : x(t.x), y(t.y) {} B(const A& a) : x(a.x), y(0) {} }; int main() { S s = {1}; B b1 = s; // Compiles OK on MSVC++; // Fails on gcc - conversion from ‘S’ to non-scalar type ‘B’ requested B b2(s); // Fails on both - Error: y is not a member of S in B::B<S>(const T &) } ``` I understand why the line `B b2(s);` fails - the `explicit` constructor matches so it's tried; but `t.y` doesn't exist. Fine. But I can't work out whether MSVC++ is correct in allowing `B b1 = s;`, or whether gcc is correct in rejecting it. MSVC++ is constructing a temporary from `A::A(const S&)`, and using that to initialise `b1` via `B::B(const A&)`; I'm not sure why gcc errors. Which compiler's right? (As an after note, if I remove the `explicit` both compilers reject `B b1 = s;` - presumably because the templated constructor is now fair game for the implicit construction of the temporary.) Edit: From the comments, it appears the MSVC++ also rejects the `B b1 = s;` line in Visual Studio 2012, so the consensus seems to be it really is an error. In which case - what is the nature of the error? What does that error message mean?