Consider the code below:
// no forward declarations
//
// template<typename T>
// class A;
//
// template<typename T>
// void swap(A<T>& lhs, A<T>& rhs);
template<typename T>
class A {
int m_i;
public:
// template<typename T1>
// friend void swap<T1>(A<T1>& lhs, A<T1>& rhs); // all instantiations of swap()
// are friends: not restrictive
// friend void swap<>(A<T>& lhs, A<T>& rhs); // restrictive: only T instantiation
// is a friend, but it requires
// forward declaration
friend void swap<>(A& lhs, A& rhs); // note absence of brackets in arguments:
// restrictive as above, but no forward
// declaration required. Why not??
A(int i = 0) : m_i{i} { }
};
template<typename T>
void swap(A<T>& lhs, A<T>& rhs) {
A<double> cA;
// cA.m_i = 0; // compile-time error: swap<int> instantiation
// is NOT a friend of A<double>
//...
}
int main() {
A<int> cA1, cA2; // A<int> instantiation
swap(cA1, cA2);
return 0;
}
Code above compiles.
In class A, friend void swap<>(A<T>& lhs, A<T>& rhs)
which requires a forward declatation seems to behave the same way as friend void swap<>(A& lhs, A& rhs)
without the need for a forward declaration.
Can anyone explain, is there a difference between the two except that one requires a forward declaration, and the other does not? In what ways are they different to that effect?