I have a class that I have written which does type erasure. The public interface is:
template <typename T>
value(const T &t);
value(value &&v);
template <typename T>
operator T() const;
When I create a value instance from a std::string I have no problems, everything works as expected. When I try to get the std::string back out, using static_cast<std::string>(val)
, where val
is an instance of value that is holding a std::string, I get the following error from VS2012:
error C2440: 'static_cast' : cannot convert from 'value' to std::string'
No constructor could take the source type, or constructor overload resolution was ambiguous
If I comment out the templated cast operator and add operator std::string() const
then it compiles. I figure that something between the std::string constructors and the templated cast operator have the same goodness of match. Could anyone suggest what is happening and how to fix it?
Igor explained the problem. Here's my suggested solution:
Your class is obviously only intended to store one type of object at a time, so make that explicit. Replace the conversion functions with a real function:
template <typename T>
T get() const;
Now call it like this:
std::string myString = myValue.get<std::string>( );
No ambiguity. No chance of the wrong function being called and messing everything up. And I'd argue that it is now more readable.
std::string
has several constructors capable of being called with one parameter - e.g. one taking const string&
, and another taking const char*
. What should T
resolve to, then?
From the C++ standard:
5.2.9p4 Otherwise, an expression e can be explicitly converted to a type
T
using astatic_cast
of the formstatic_cast<T>(e)
if the declarationT t(e);
is well-formed, for some invented temporary variablet
.
In your case, the declaration std::string t(val);
is ill-formed.
Following works with std::string (if you can return a reference).
static_cast<const std::string&>(val);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With