Friend function from another namespace
/** module.h */
#pragma once
class A {
friend void helpers::logValue(const A &);
int _val;
public:
A() {}
};
namespace helpers {
static void logValue(const A &a) {
std::cout << a._val; // <== ERROR: '_val' is not accessible
}
}
How do I declare the friend function in another namespace?
Solution 1:
One possible way of solving this is as shown below:
class A;//forward declaration for class A
namespace helpers{
static void logValue(const A &a); //declaration
}
///////////////////////////////////////////
class A {
friend void helpers::logValue(const A &);
int _val;
};
namespace helpers {
static void logValue(const A &a) {
std::cout << a._val; // works now
}
}
The output of the above program can be seen here.
Solution 2:
To come up with a solution, it is necessary to work backward.
We want this to work with _val
a private
member of class A
.
namespace helpers {
static void logValue(const A &a) {
std::cout << a._val;
}
}
Step 1 For the function definition above to work there must be a preceding definition of class A
visible the compiler, and that class definition must specify that helpers::logValue()
(with the appropriate signature i.e. return type and arguments) is a friend
. So before the definition above of helpers::logValue()
we must place;
class A {
friend void helpers::logValue(const A &);
int _val;
};
Step 2 For that friend
declaration in Step 1 to be valid, the compiler must know about helpers::logValue()
. That requires a declarative region of namespace helpers
visible to the compiler that declares a function logValue()
with the same signature, and that must be before the definition of A
. So, before our definition of class A
, we must do something like;
namespace helpers{
static void logValue(const A &a);
}
Step 3 The compiler will choke on this declaration of helpers::logValue()
if there is no declaration of class A
visible. We already have a class definition (created in Step 1), so we cannot create another one (that would break the one-definition rule). But we can add a declaration before the code from Step 2.
class A;
Putting those steps together, we put the code from the steps together in reverse order (i.e. put the code from Step 3 first, follow up with the code from Step 3, etc). We then get
// Step 3
class A;
// Below Step 3 comes code from Step 2
namespace helpers{
static void logValue(const A &a); // works since A is declared
}
// Below Step 2 comes code from Step 1
class A {
friend void helpers::logValue(const A &); // works since helpers::logValue() is declared
int _val;
};
// And now we come to the function definition we want to have work
namespace helpers {
static void logValue(const A &a) {
std::cout << a._val;
}
}