Reputation: 21
Why is implicit type conversion not performed for user-defined type in the following source code?
An implicit type conversion to type A should occur on the commented line, but it did not happen and an error occurred on that line.
I would like to know the grammatical rules and solutions for this error.
#include <iostream>
using namespace std;
class A {
int v;
public:
A(int _v): v(_v) {}
operator int (void) const {
return v;
}
friend ostream& operator << (ostream& os, const A& s) {
return os << "A: " << s.v;
}
};
class B {
int x, y;
public:
B(int _x, int _y): x(_x), y(_y) {}
operator A(void) const {
return A(x+y);
}
};
int main(void)
{
B b(1,2);
cout << A(b) << endl;
cout << (A)b << endl;
cout << b << endl; // error --> why?
return 0;
}
--> Additional Question
Thanks for Sam Varshavchik's reply .
Defining class A as below solves the problem.
class A {
int v;
public:
A(int _v): v(_v) {}
operator int (void) const {
return v;
}
friend ostream& operator << (ostream& os, const A& s);
};
ostream& operator << (ostream& os, const A& s){
return os << "A: " << s.v;
}
//////////////
class A {
int v;
public:
A(int _v): v(_v) {}
operator int (void) const {
return v;
}
friend ostream& operator << (ostream& os, const A& s){
return os << "A: " << s.v;
}
};
ostream& operator << (ostream& os, const A& s);
Whether or not to declare "operator <<" as a friend doesn't seem to matter here. Since the function is a global function, it can be referenced in other classes or other funcitons. I think it matters whether the block defining the function is inside or outside class A. Why is function declaration necessary when using inner definition? I want to know the grammatical basis.
Upvotes: 2
Views: 114
Reputation: 12928
When a friend function is defined inside a class it will only be found through ADL.
In your first two lines you are providing an A
, so ADL kicks in and finds the operator<<
. When passing a B
ADL will not help find your operator<<
so a conversion is never considered by the compiler.
Some more details on ADL.
Upvotes: 2
Reputation: 118292
This must have something to do with arcane rules related to the relationship between overload resolution, friend functions, and implicit conversions. Because this is not just about implicit conversions, here. You're also defining an overload operator<<
that's a friend function.
By simply getting rid of the friend function, the following code compiles fine, on gcc 9.2. It also doesn't hurt to get rid of using namespace std;
, as well:
#include <iostream>
class A {
int v;
public:
A(int _v): v(_v) {}
operator int (void) const {
return v;
}
};
std::ostream& operator << (std::ostream& os, const A& s) {
return os << "A: " << (int)s;
}
class B {
int x, y;
public:
B(int _x, int _y): x(_x), y(_y) {}
operator A(void) const {
return A(x+y);
}
};
int main(void)
{
B b(1,2);
std::cout << A(b) << std::endl;
std::cout << (A)b << std::endl;
std::cout << b << std::endl; // No more error
return 0;
}
Upvotes: 3