Kind of a random question...
What I'm looking for is a way to express a cast operation which uses a defined operator of the class instance I'm casting from, and generates a compile-time error if there is not a defined cast operator for the type. So, for example, what I'm looking for is something like:
template< typename RESULT_TYPE, typename INPUT_TYPE >
RESULT_TYPE operator_cast( const INPUT_TYPE& tValue )
{
return tValue.operator RESULT_TYPE();
}
// Should work...
CString sString;
LPCTSTR pcszString = operator_cast< LPCTSTR >( sString );
// Should fail...
int iValue = 42;
DWORD dwValue = operator_cast< DWORD >( iValue );
Interesting side-note: The above code crashes the VS2005 C++ compiler, and doesn't compile correctly in the VS2008 C++ compiler due to what I'm guessing is a compiler bug, but hopefully demonstrates the idea.
Anybody know of any way to achieve this effect?
Edit: More rationale, to explain why you might use this. Say you have a wrapper class which is supposed to encapsulate or abstract a type, and you're casting it to the encapsulated type. You could use static_cast<>, but that might work when you wanted it to fail (ie: the compiler chooses an operator which is allowed to convert to the type you asked for, when you wanted a failure because that operator is not present).
Admittedly it's an uncommon case, but it's annoying that I can't express exactly what I want the compiler to do in an encapsulated function... hence the question here.
The code you posted works with the Cameau compiler (which is usually a good indication that it's valid C++).
As you know a valid cast consists of no more than one user defined cast, so a possible solution I was thinking of was adding another user defined cast by defining a new type in the cast template and having a static assert that no cast is available from the new type to the result type (using boost is_convertible), however this doesn't distinguish between cast operators and cast constructors (ctor with one argument) and alows additional casts to take place (e.g. void*
to bool
). I'm not sure if making a distinction between cast operators and cast constructors is the the correct thing to do but that's what the question states.
After a couple of days mulling this over it hit me, you can simply take the address of the cast operator. This is slightly easier said than done due to C++'s hairy pointer to member syntax (it took me way longer than expected to get it right). I don't know if this works on VS2008, I only checked it on Cameau.
template< typename Res, typename T>
Res operator_cast( const T& t )
{
typedef Res (T::*cast_op_t)() const;
cast_op_t cast_op = &T::operator Res;
return (t.*cast_op)();
}
Edit: I got a chance to test it on VS2005 and VS2008. My findings differ from the original poster's.