C++ could solve this without badges, if it didn't have a very tiny, silly misfeature.<p>The misfeature is this: a class A can only declare a specific member function of class B as a <i>friend</i>, if that B member function is public!<p>Example:<p>The idea here is that Device has a static member function called <i>Device::registrationHelper</i>. That specific function (not the entire Device class) is declared a friend to VFS, and so that function can call <i>VFS::registerDevice</i>.<p>[Edit: this doesn't quite match the Badge solution, though. If this worked, it would have the problem that the <i>registrationHelper</i> has access to all of <i>VFS</i>, which is almost as bad as the entire <i>Device</i> class being a friend of <i>VFS</i>. That is one of the problems which motivate Badge. Nice try, though! The C++ restriction is probably worth fixing anyway. What the C++ friendship mechanism really needs here is to be able to say that a specific member function in B is allowed to access a specific member of A.]<p><pre><code> class Device;
class VFS;
class Device {
public: // we want this private!
static void registrationHelper(VFS &v, Device &d);
private:
void registerWith(VFS &vfs) { registrationHelper(vfs, *this); }
};
class VFS {
private:
void registerDevice(const Device &);
friend void Device::registrationHelper(VFS &, Device &);
};
void Device::registrationHelper(VFS &v, Device &d)
{
v.registerDevice(d);
}
</code></pre>
But we are forced to make <i>Device::registrationHelper</i> public, which defeats the purpose: anyone can call it and use it is a utility to register devices with VFSs.<p>If we make Device::registrationHelper private to prevent this, then the "friend void Device::registrationHelper" declaration in VFS fails.<p>This is an oversight; the privacy of the <i>Device::registrationHelper</i> identifier means that the <i>VFS</i> class is not even allowed to mention its name for the sake of declaring it a friend.<p>That should be fixed in C++. Declaring a function a <i>friend</i> shouldn't require it to be accessible; we are not lifting its address or calling it; we are just saying that it can call us. Allowing a function to call us is not a form of <i>access</i> to that function, yet is being prevented by <i>access</i> specifiers.