Technical.
Converting to (almost) any type of T can be done using the member function operator T
It is called implicitly by default, and if you declare it const , it can also be called on a const object.
Thus:
struct MyType { operator int() const { return 1; } };
Problems & hellip;
The presence of an implicit conversion to the base type allows a free game for all built-in operators, including
- Arithmetic operators.
- Boolean operators.
- Relational operators.
So, you better make sure that it all works the way you want.
And it can be a lot of work!
There are also potential overload resolution issues for calls involving instances of your type.
In short, implicit conversion to int or pointer or any built-in type usually costs more than it costs.
An exception where this may be useful is that the class is used a lot in the library.
What can you do about it.
Avoid implicit conversion, but suggest explicit conversion.
The best common explicit conversion is IMHO, a named member function.
An alternative is operator T with the explicit keyword prefix, which is supported for this use in C ++ 11 and later (in C ++ 03 it can only be used for constructors).
If you want the result through << to behave as if an implicit conversion is being performed, just define operator<< .
And similarly for other situations, when an implicit conversion appears to be a general solution: just determine what is appropriate for that particular situation and avoid introducing a general implicit conversion.
To provide implicit conversion to an inline type and still avoid being "free for everyone" for inline operators, you can use a template-type conversion, for example. eg:
#include <iostream> template< class A, class B > struct Is_t_; template< class Type > struct Is_t_<Type, Type> { using T = void; }; template< class A, class B > using If_is_ = typename Is_t_<A, B>::T; struct Bad_string { operator const char* () const { return "666!"; } Bad_string( char const* = 0 ) {} }; auto operator==( Bad_string const&, Bad_string const& ) -> bool { return true; } struct Good_string { template< class Type, class Enabled_ = If_is_<const char*, Type>> operator Type() const { return "42 :)"; } Good_string( char const* = 0 ) {} }; auto operator==( Good_string const&, Good_string const& ) -> bool { return true; }
Ironically, when DO_GOOD defined, this code is issued by the Visual C ++ 2015 update 1 compiler, the so-called "ICE" (internal Error compiler).
A workaround for this compiler is to define If_is_ instead
template< class A, class B > using If_is_ = std::enable_if_t< std::is_same<A, B>::value >;