14

Let's have this code:

Test1 t1;
Test2 t2;
t1 = t2;

I believe there are three (or more?) ways how to implement t1 = t2

  • to overload assign operator in Test1
  • to overload type cast operator in Test2
  • to create Test1(const Test2&) conversion constructor

According to my GCC testing, this is the priority of what is used:

  1. assign operator
  2. conversion constructor and type cast operator (ambiguous)
  3. const conversion constructor and const type cast operator (ambiguous)

Please help me understand why this priority.

I use this code for testing (uncomment some lines to try out)

struct Test2;
struct Test1 {
  Test1() { }
  Test1(const Test2& t) { puts("const constructor wins"); }
//  Test1(Test2& t) { puts("constructor wins"); }
//  Test1& operator=(Test2& t) { puts("assign wins"); }
};

struct Test2 {
  Test2() { }
//  operator Test1() const { puts("const cast wins"); return Test1(); }
//  operator Test1() { puts("cast wins"); return Test1(); }
};


int main() {
  Test1 t1;
  Test2 t2;
  t1 = t2;
  return 0;
}
2
  • Test1::Test1(const Test2&) is not a "copy constructor", it is a "converting constructor". Commented Sep 9, 2012 at 1:02
  • This post explains exactly why conversion operator is of higher precedence: stackoverflow.com/questions/1384007/… Commented Sep 9, 2012 at 1:20

2 Answers 2

17

The statement t1 = t2; is equivalent to:

t1.operator=(t2);

Now the usual rules of overload resolution apply. If there's a direct match, that's the chosen one. If not, then implicit conversions are considered for use with the (automatically generated, "implicitly defined") copy-assignment operator.

There are two possible implicit, user-defined conversions. All user-defined conversions count equal, and if both are defined, the overload is ambiguous:

  • Convert t2 to a Test1 via the Test1::Test1(Test2 const &) conversion constructor.

  • Convert t2 to a Test1 via the Test2::operator Test1() const cast operator.

Sign up to request clarification or add additional context in comments.

10 Comments

In @Luchian's second ideone example, the conversion function wins because it binds a Test2& to t2, not a const Test2&. I thought ideone.com/U38vK was supposed to be ambiguous too, but it seems g++ prefers the constructor.
Aha. g++ DOES call them ambiguous if you ask for -pedantic. Naughty default g++.
@KerrekSB: If the cast operator is not constant, it beats the conversion constructor and there is no ambiguity. liveworkspace.org/code/7795254ae49b4d6350f0ede57615e4c6
@JanTuroň: Yes, I know. And if you make the constructor non-const as well, you can get the ambiguity back.
@JanTuroň: The exact same reason.
|
0

when I use following code than priority is given first to the constructor rather than cast operator

 #include<iostream>
 using namespace std;
 class C1;
 class C2
 {
      int x;
 public:
     operator C2()
     {
       C2 temp;
       cout<<"operator function called"<<endl;
       return temp;
    }
 };
class C1
{
   int x;
public:
   C1():x(10){}
   C1(C2)
  {
    cout<<"constructor called"<<endl;
  }
};
 int main()
{
  C1 obj1;
  C2 obj2;
  obj1=obj2;
}

Output Constructor called

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.