There is no way to do this directly with friendship, but you can achieve a similar effect with a modification of tag-based dispatching:
class C
{
public:
class AccessTag
{
friend class C;
friend void F();
private:
AccessTag() {}
};
void functionToAccess(AccessTag)
{
std::cout << "Restricted function called!\n";
}
};
void F()
{
C c;
c.functionToAccess(C::AccessTag()); // OK
}
void nonF()
{
C c;
c.functionToAccess(C::AccessTag()); // error, nonF cannot access ctor of C::AccesTag
}
The idea is to only allow functionToAccess
to be called by those who can construct a C::AccessTag
object. And because of its private constructor, C::AccessTag
can only be constructed by its friends. These are C
(so that it can call functionToAccess
itself, as it could any other of its private functions), and F
. F
cannot access any other non-public members of C
, because it is not a friend of C
.
You can even have different access tags for different member functions (or groups of member functions).