I want to know why one of the following two codes compiles while the other does not. In the first code, createB is a stand alone function. In the second code the function createB is a member of class A.
The first one compiles.
#include <iostream>
class A;
class B {
public:
B() { std::cout << "B"; }
friend B createB();
};
class A {
public:
A() { std::cout << "A"; }
};
B createB() { return B(); }
int main() {
A a;
B b = createB();
}
The second one does not.
#include <iostream>
class A;
class B {
public:
B() { std::cout << "B"; }
friend B A::createB();
};
class A {
public:
A() { std::cout << "A"; }
B createB() { return B(); }
};
int main() {
A a;
B b = a.createB();
}
CodePudding user response:
Case 1
In the first snippet, createB
is a free(standalone) function and it is not mandatory that the friend declaration names an existing function. So this works and also implicitly declares a function named createB
with return type of B
in the global namespace, though this createB
is not visible through ordinary lookup.
Case 2
The problem in the 2nd example is that A
is an incomplete at the point of the friend declaration friend B A::createB();
.
To solve this, we can move the definition of A
to before B
so that A
is complete at the point of the friend declaration. Additionally, we can provide the definition of createB
after B
has been defined as shown below:
//forward declaration so that B can be used in declaration B createB();
class B;
class A {
public:
A() { std::cout << "A"; }
//this is declaration
B createB();
};
class B {
public:
B() { std::cout << "B"; }
friend B A::createB(); //this works as now at this point A is complete since we moved the definition of A to before B
};
//this is definition
B A::createB() { return B(); }
int main() {
A a;
B b = a.createB();
}