Implicit conversion from user type to primitive type in C ++

I can find a lot of information about implicit conversion from, say, int to user type. those. if the constructor accepts int as its parameter and is not preceded by "explicit", then implicit conversions may occur.

What if I want my class to implicitly convert to int?

For example, which function should be added either inside or outside SimpleClass, so that the main function will compile and output "1" to the console? (see comments)

#include <iostream> class SimpleClass { private: int m_int; public: SimpleClass(int value) : m_int(value) {} }; int main(int argc, const char * argv[]) { SimpleClass simpleclass(1); int i = simpleclass; // does not complile std::cout << i << std::endl; // should output "1" to the console return 0; } 
+7
c ++ implicit-cast
source share
3 answers

Implicit conversions can be defined in two ways:

  • implicit constructor with one argument.
  • implicit conversion function (aka conversion operator), N3337 12.3.2

A later version allows you to define a conversion from a class type to a primitive type. Just add

 class SimpleClass { // ... operator int() const; }; SimpleClass::operator int() const { return m_int; } 
+10
source share

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; } #if defined( DO_GOOD ) using String = Good_string; #elif defined( DO_BAD ) using String = Bad_string; #else # error "Define either DO_GOOD or DO_BAD, please." #endif auto main() -> int { String a, b; (void) (a == "alfalfa"); // Errs for Bad_string (void) (a + 1); // Compiles for Bad_string. } 

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 >; 
+4
source share

To enable the conversion of your class to int , do

 operator int() const { return m_int; } 
+1
source share

All Articles