youssef
youssef

Reputation: 623

how does the compiler choose automatic type conversion method

In this code, two methods were used to allow conversion of Y object into X object. compiling by g++ always choose constructor. if constructor is private like :
private : Y(const X&){std::cout << "Y constructor...\n" ; }
conversion is prevented either by operator or constructor. if constructor is private and explicit
private : explicit Y(const X&){std::cout << "Y constructor...\n" ; }
compiler use operator instead. Is it the usual way to prevent auto conversion by making conversion constructor private and what is the rule that compiler use to make such kind of conversion.

#include <iostream>

class Y ;

class X {
public:
  operator Y()const ;
};

class Y {
public:
  Y(){}
private : 
  explicit Y(const X&){std::cout << "Y constructor...\n" ; }
};

X::operator Y() const { std:: cout << "Operator Y...\n" ;
 return Y ();
}


void func(Y Y_object) {}

int main() {
  X X_object ;
  Y Y_object ;

  func(X_object) ;
  Y_object = X_object ;
}

Upvotes: 1

Views: 223

Answers (2)

David G
David G

Reputation: 96810

Conversion functions and converting-constructors designate conversions from the type for which the conversion function/constructor is made to the type that is taken in the parameter. In other words, you are converting from an X to a Y and not the other way around as you said.

When there is a conversion from X to Y, the compiler considers the best conversion possible through function overload resolution. Since access control is not considered during overload resolution, it is possible for a private conversion to be chosen over one that is public if the private one is a more viable conversion. There can also be an ambiguity between two conversions if they are both equally viable.


Calling the function func(X_object) requires an implicit conversion from X to Y. Considering both X::operator Y() const and the converting constructor explicit Y::Y(const X&), the conversion operator is chosen because the constructor is marked as explicit and therefore only can be called through the direct-initialization syntax or an explicit cast.

func(Y(X_object));
func(static_cast<Y>(X_object));

These both call the explicit converting-constructor because the argument type of the constructor and parameter matches exactly.


The same situation occurs when using copy-assignment to implicitly convert an X to a Y. The implicit conversion operator is a more viable function than the explicit constructor:

Y_object = X_object; // calls X_object.operator Y()

If direct-initialization syntax or an explicit cast is used, the converting-constructor will be the best viable function.


To prevent an implicit conversion from an X to a Y, it is best that you give Y an explicit constructor rather than an explicit conversion operator. In this case there doesn't seem to be a reason to make the constructor private unless you want to prevent the conversion all together, but if you wanted to do that then simply leave the constructor undeclared.

Upvotes: 2

kraskevich
kraskevich

Reputation: 18556

The most usual way to prevent implicit type conversion is not to declare conversion operator at all and make the constructor explicit. However, if you want to keep the conversion operator, you can make explicit too using explicit keyword:

class X {
public:
  explicit operator Y() const;
};

Upvotes: 0

Related Questions