Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do conversion operators work in C++?

Consider this simple example:

template <class Type> class smartref { public:     smartref() : data(new Type) { }     operator Type&(){ return *data; } private:     Type* data; };  class person { public:     void think() { std::cout << "I am thinking"; } };  int main() {     smartref<person> p;     p.think(); // why does not the compiler try substituting Type&? } 

How do conversion operators work in C++? (i.e) when does the compiler try substituting the type defined after the conversion operator?

like image 974
Khaled Alshaya Avatar asked Aug 20 '09 18:08

Khaled Alshaya


People also ask

What is a conversion operator?

A conversion operator, in C#, is an operator that is used to declare a conversion on a user-defined type so that an object of that type can be converted to or from another user-defined type or basic type. The two different types of user-defined conversions include implicit and explicit conversions.

What do you mean by conversion in C?

In C programming, we can convert the value of one data type ( int, float , double , etc.) to another. This process is known as type conversion.

What is a conversion operator CPP?

Conversion Operators in C++ In C++, the programmer abstracts real-world objects using classes as concrete types. Sometimes, it is required to convert one concrete type to another concrete type or primitive type implicitly.

What is the function of conversion?

You can define a member function of a class, called a conversion function, that converts from the type of its class to another specified type.


1 Answers

Some random situations where conversion functions are used and not used follow.

First, note that conversion functions are never used to convert to the same class type or to a base class type.

Conversion during argument passing

Conversion during argument passing will use the rules for copy initialization. These rules just consider any conversion function, disregarding of whether converting to a reference or not.

struct B { }; struct A {   operator B() { return B(); } }; void f(B); int main() { f(A()); } // called! 

Argument passing is just one context of copy initialization. Another is the "pure" form using the copy initialization syntax

B b = A(); // called! 

Conversion to reference

In the conditional operator, conversion to a reference type is possible, if the type converted to is an lvalue.

struct B { }; struct A {   operator B&() { static B b; return b; } };  int main() { B b; 0 ? b : A(); } // called! 

Another conversion to reference is when you bind a reference, directly

struct B { }; struct A {    operator B&() { static B b; return b; } };  B &b = A(); // called! 

Conversion to function pointers

You may have a conversion function to a function pointer or reference, and when a call is made, then it might be used.

typedef void (*fPtr)(int);  void foo(int a); struct test {   operator fPtr() { return foo; } };  int main() {   test t; t(10); // called! } 

This thing can actually become quite useful sometimes.

Conversion to non class types

The implicit conversions that happen always and everywhere can use user defined conversions too. You may define a conversion function that returns a boolean value

struct test {   operator bool() { return true; } };  int main() {   test t;   if(t) { ... } } 

(The conversion to bool in this case can be made safer by the safe-bool idiom, to forbid conversions to other integer types.) The conversions are triggered anywhere where a built-in operator expects a certain type. Conversions may get into the way, though.

struct test {   void operator[](unsigned int) { }   operator char *() { static char c; return &c; } };  int main() {   test t; t[0]; // ambiguous }  // (t).operator[] (unsigned int) : member // operator[](T *, std::ptrdiff_t) : built-in 

The call can be ambiguous, because for the member, the second parameter needs a conversion, and for the built-in operator, the first needs a user defined conversion. The other two parameters match perfectly respectively. The call can be non-ambiguous in some cases (ptrdiff_t needs be different from int then).

Conversion function template

Templates allow some nice things, but better be very cautious about them. The following makes a type convertible to any pointer type (member pointers aren't seen as "pointer types").

struct test {   template<typename T>   operator T*() { return 0; } };  void *pv = test(); bool *pb = test(); 
like image 52
Johannes Schaub - litb Avatar answered Sep 30 '22 22:09

Johannes Schaub - litb