Reputation: 5034
I have these codes:
class Type2 {
public:
Type2(const Type1 & type);
Type2(int);
const Type2 & operator=(const Type2 & type2);
//....
};
...
Type1 t1(13);
Type2 t2(4);
t2=t1;
As I understood, the 1-argument constructors of Type2 each without an explicit keyword should mean any Type1 objects or int values can be implicitly conveted to Type2 objects.
But in the last line t2=t1;, MS Visual Studio gives me this compile error:
....error C2679: binary '=' : no operator found which takes a right-hand operand of type 'Type1' (or there is no acceptable conversion)....
Seems like MS Visual Studio insisting t2=t1; must match an assignment operator with lhs=Type2 and rhs=Type1. Why can't it implicitly cast rhs to t2 and then do the copying with the Type2=Type2 operator?
Upvotes: 3
Views: 2744
Reputation: 56038
This code:
#include <iostream>
using ::std::cerr;
class Barney;
class Fred {
public:
Fred() { }
Fred(const Barney &b) { cerr << "Using conversion constructor.\n"; }
};
class Barney {
public:
Barney() { }
operator Fred() const { cerr << "Using conversion operator.\n"; return Fred(); }
};
int main(int argc, const char *argv[])
{
const Barney b;
Fred f;
f = b;
return 0;
}
generates this error in gcc 4.6:
g++ -O3 -Wall fred.cpp -o a.out
fred.cpp: In function ‘int main(int, const char**)’:
fred.cpp:23:8: error: conversion from ‘const Barney’ to ‘const Fred’ is ambiguous
fred.cpp:21:17: note: candidates are:
fred.cpp:16:4: note: Barney::operator Fred() const
fred.cpp:10:4: note: Fred::Fred(const Barney&)
fred.cpp:7:7: error: initializing argument 1 of ‘Fred& Fred::operator=(const Fred&)’
Compilation exited abnormally with code 1 at Sun Jun 19 04:13:53
Now, if I remove the const
after operator Fred()
, it then compiles, and uses the conversion constructor. If I also remove the const
from the declaration of b
in main
, it then prefers the conversion operator.
This all fits the overload resolution rules. And gcc generates the appropriate ambiguity error when it can't pick between the conversion operator and the conversion contructor.
I notice that in the examples you gave, the conversion operator is missing a const
. This means that there will never be a case in which using the conversion operator or the converting constructor is ambiguous.
Upvotes: 1
Reputation: 5034
I've found the answer. Because my Type1 got a conversion operator
class Type1 {
public:
Type1 (int );
operator Type2() ;//casting to Type2
....
};
This is something called "dual-direction implicit conversion"
Upvotes: 2