Implicit conversions from classes and types

I am studying the conversion of constructors and conversion operators in C ++. So far, I have learned that any implicit constructor that accepts only one parameter (and any number of optional default arguments) is an implicit conversion of a class type to a class type THAT, for example, if the class defines a constructor that has one parameter of type int I can use int wherever an object of this class type is required:

(assuming class_type has an overloaded + = operator)

 class_type a; a+=5; 

in this case 5 is implicitly converted (via the conversion constructor) to class_type and the overloaded operator is called.

Now (at least for me) the hard part: I know that I can define the conversion operator as a member function:

 operator int() {....}; 

which converts the class_type object to a primitive int type, and I can use this conversion, for example:

 class_type a; a+5; 

in this case, I read that the object is converted to int through its conversion statement, and then the buil-in sum statement is called. But what if I defined an overloaded + operator to take two class_type objects as my arguments? sort of

class_type operator+(const class_type&,const class_type &c);

how should the compiler know which one can be called through a function mapping? Is conversion to int performed implicitly when only the inline operator is defined?

thanks!

edit:

Actually, I tried to write some code to try it out effectively, it turned out that my compiler (g ++) did not cause any ambiguous call error!

this is the class header (along with the non-memeber + function declaration):

 #include <iostream> class wrapper { friend std::ostream &operator<<(std::ostream&,const wrapper&); public: wrapper()=default; wrapper(int); int get(); operator int() const; wrapper operator+(int); private: int a=10; }; std::ostream &operator<<(std::ostream&,const wrapper&); 

and this is the main code:

 #include "wrapper.h" int main() { using namespace std; wrapper w1; wrapper w2(5); cout<<w1<<" "<<w2<<endl; w1+1; } 

now I have defined the conversion constructor from int to wrapper AND the conversion operator from class type to int (I also overloaded the <<output operator to print some results), but when the compiler evaluates the expression w1+1 , it seems fine. How is this possible?

+6
source share
2 answers

If you have, for example, the following class declaration containing a transform constructor and a transform operator

 struct A { A( int x ) : x( x ) {} operator int() const { return x; } int x; }; const A operator +( const A &a1, const A &a2 ) { return A( a1.x + a2.x ); } 

that statement

 a1 + a2; 

where a1 and a2 are declared as, for example,

 A a1( 10 ); A a2( 20 ); 

will be well formed because there is no need to call the transform function. Both operands correspond to declarations of the parameters of the + operator.

However, if you write, for example,

 a1 + 20; 

when the compiler throws an error because there is ambiguity. The compiler can either use the A( int ) conversion constructor to convert the second operand to type A , and invoke the operator defined for objects of type A Or he can use the operator int to convert the first operand to int and call the built-in operator + for objects of type int .

To avoid this ambiguity, you can declare either a constructor or an operator (or both) using the explicit function specifier.

for instance

  explicit A( int x ) : x( x ) {} 

or

  explicit operator int() const { return x; } 

In this case, there would be only one implicit transformation, and there would be no ambition.

I would like to add the above description that sometimes some conversion operators can be called implicitly, even if they are declared using the explicit function specifier.

For example, according to the C ++ standard (6.4 Selection)

  1. ... The value of the condition that is the expression is the value of the expression contextually converted to bool for other operators than the switch;

and (5.16 Conditional operator)

1 Group of conditional expressions from right to left. The first expression is contextually converted to bool (section 4).

So, for example, if the above class has the following conversion operator declared using the explicit function specifier

 explicit operator bool() const { return x != 0; } 

nevertheless, it will be called implicitly, for example, in the following statement

 A a( 10 ); std::cout << ( a ? "true" : "false" ) << std::endl; 

Here a will be converted to an object of type bool in the conditional statement.

EDIT: after you updated your question, this expression

 w1+1; 

is an exact match for the operator

 wrapper operator+(int); 

No conversion is required. Thus, the code compiles successfully.

+11
source

This is something you can easily try and see what the compiler does:

 #include <iostream> struct ABC { int v; ABC(int x) : v(x) { } operator int() const { return v; } void operator +=(ABC const &that) { v += that.v; } }; ABC operator+(ABC const &lhs, ABC const &rhs) { return { lhs.v + rhs.v }; } int main() { ABC a(5); std::cout << a + 1 << '\n'; a += 10; std::cout << a << '\n'; } 

What if I defined an overloaded + operator to take two class_type objects as arguments?

NKU

error: ambiguous overload for "operator +" (operand types are "ABC" and "int")

The compiler sees two candidates: operator+(int, int) <built-in> and ABC operator+(const ABC&, const ABC&) . This means that it can implicitly convert not only 5 to a + 5 to a , but also a to int . Publish these transformations and operator+ functions will become potential matches.

How should the compiler know which one can be called through a function mapping?

He therefore does not know the mistake.

Is conversion to int performed implicitly when only the inline operator is defined?

Yes, otherwise it does not automatically convert class_type to int . However, an int before class_type will happen implicitly unless you create the constructor class_type explicit :

 explicit ABC(int x) : v(x) { } 

If you have access to C ++ 11, you also make the conversion function explicit:

 explicit operator int() const { return v; } 
+3
source

All Articles