2014-09-02 15:57 GMT+02:00 Andrzej Krzemienski
2014-09-02 13:39 GMT+02:00 Andrzej Krzemienski
: 2014-09-02 11:23 GMT+02:00 Dean Michael Berris
: I just verified that your code example works with 1.55 on VS2010, so it is a regression. I will not be able to have a look at it for the next couple of days. I would like to determine why it even works on 1.55. The converting constructor from arbitrary U is also explicit in 1.55, so it works because of some sequence of conversions that I cannot figure out right now.
Right. My hunch is that 1.56 now has suppression for the cases where references would have been deduced (as discussed in
http://www.boost.org/doc/libs/1_56_0/libs/optional/doc/html/boost_optional/d... ). Maybe the suppression applies even for the case when the conversion operator may have been useful for copy initialization.
However, it works fine with GCC. It looks like VC++ compiler has a bug in overload resolution in copy initialization. It should never consider explicit constructors.
Ok, I managed to isolate the problem. The following code does not compile on VC++2010, although it is correct:
struct A { A(int &&) {} A(A &&) {}
template <typename T> explicit A(T&&) {} };
struct B { operator A() { return A(1); } operator int() { return 0; } };
int main() { A t = B(); }
The unambiguous conversion path is to use B::operator A(), but VC++ somehow finds it ambiguous.
And the above incorrect behaviour is the consequence of a more simple bug in VC++. It allows two user defined conversions in copy initialization: struct A { A(int &&) {} }; struct B { operator int() { return 0; } }; int main() { A t = B(); } This works in VC++, although the code is incorrect.