I wanted to somehow extend the Microsoft type _variant_t so it accepts implicit/explicit conversions to/from additional types. To do so, I wrote the following class:
class value_type
{
public:
/* Constructors */
value_type(const std::string& str) : m_variant(str.c_str()) {}
template <typename Type> value_type(const Type& value) : m_variant(value) {}
/* Conversion operators */
operator const _variant_t&() const { return m_variant; }
operator std::string() const { return static_cast<const char*>(m_variant); }
template <typename Type> operator Type() const { return static_cast<Type>(m_variant); }
private:
_variant_t m_variant;
};
That is, if every instance of _variant_t in the code is replaced with value_type, it “works” the same.
Lets consider the following function, which returns a _variant_t:
_variant_t foo();
If I write:
std::string bar()
{
value_type v = foo();
return v;
}
It compiles just fine.
But if I change the previous code like that:
std::string bar()
{
return value_type(foo());
}
or:
std::string bar()
{
return static_cast<std::string>(value_type(foo()));
}
The compilation fails with the following message:
configuration.cpp(41) : error C2668: ‘std::basic_string<_Elem,_Traits,_Ax>::basic_string’ : ambiguous call to overloaded function
If I remove the template <typename Type> operator Type... line, everything compiles.
Now I understand what the compilater says (it doesn’t know which operator to use) but I don’t understand why: It would seem logical to use the operator std::string when converting to std::string. What am I missing ?
Thank you.
The problem is that string’s constructor is overloaded. So if returning involves invoking a string constructor, then there are multiple choices: argument could be converted to
const char*,allocator<char>orstring.static_cast<string>(x)is the same asstring(x).I suppose your first faulty example should read
return string(foo());, notreturn value_type(foo());