The code shown below doesn't compile when the friend function mag() is defined inside the class, but works if defined outside class (commented). I think the difference is caused by the copy constructor used to change the argument type from A to B. Can someone explain why I should define the friend function outside?
Moreover, if class B is a template class (adding template <class T>
at the top), defining the friend function outside will also not work.
#include <iostream>
using namespace std;
class A {
};
class B {
public:
B(const A& p) {
std::cout << "Copy/Conversion constructor" << std::endl;
}
friend void mag(const B& p) {
std::cout << "Mag Inside`.\n";
}
};
//void mag(const B& p) {
// std::cout << "Mag Outside.\n";
//}
int main() {
A a;
mag(a);
return 0;
}
Because the function mag
is not declared in the global scope (you did defined and declared it when you made it a friend at the same time, but the declaration in it's own scope is still required).
You need to declare it :
class B {
public:
B(const A& p) {
std::cout << "Copy constructor" << std::endl;
}
friend void mag(const B& p) {
std::cout << "Mag Inside`.\n";
}
};
void mag(const B& p);
If you call mag
with a B
object, Argument Dependant Lookup will look into B
's scope and find the definition.
Now if B
is a template, you'll need to declare each version of mag
with the appropriate parameters (and if several exist, you'll need to help the compiler to resolve ambiguities during conversions) :
template<typename T>
class B {
public:
B(const A& p) {
std::cout << "Copy constructor" << std::endl;
}
friend void mag(const B<T>& p) {
std::cout << "Mag Inside`.\n";
}
};
void mag(const B<int>& p); // Version for B<int> declared.