Ian Collins wrote:
#include <string>
struct Value
{
Value() {}
template <typename T> operator T() { return T(); }
};
int main()
{
Value v;
int n(v);
std::string s(v);
}
My original compiler is happy with the string initialisation, but g++
whinges about the conversion being ambiguous (edited to cut the noise):
example.cc:15: error: call of overloaded 'basic_string(Value&)' is
ambiguous
candidates are:
std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const
_CharT*, const _Alloc&)
std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const
std::basic_string<_CharT, _Traits, _Alloc>&)
std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _Alloc&)
But it will happily accept
std::string s = v;
So my question is, which compiler is correct?
G++ is correct for rather obvious reasons.
Your first `std::string` initialization is ambiguous. As the compiler
told you, in the
std::string s(v);
any of the three listed constructors can be used. None of then is
"better" than the others from the overload resolution point of view.
They all are equally good, hence the ambiguity.
The
std::string s = v;
variant also technically allows several "paths" the lead to creation of
the temporary `std::string` object on the right-hand side, but one of
them is considered "better" then the others: it is "better" create a
temporary `std::string` immediately from `v` than create, say, a 'char
*` pointer from 'v' and then convert it to temporary `std::string`. In
other words, there's a clear "winner" for the overload resolution in
this case and, therefore, no ambiguity.
That's clear, thanks. That was one of those cases where the incorrect