Any visible interface, public or private (via friend), will eventually be used by other programmers for other than its intended use case simply because it is there and accessible. For the maintainer of an interface with a single intended purpose, what should be a clean, tidy modification within the scope of its intended use ends up breaking all kinds of unrelated code that the maintainer wasn't even aware of that is using the interface in ways the designer didn't anticipate. It is a common form of architectural rot. Reducing the incidence of this in large code bases is usually enforced by soft means, like sternly worded comments, vigorous policing, etc but that only goes so far. Ideally, an access policy would be in the code itself and enforced by the compiler.
The public/private labels don't address this. If you make things public, the world has the ability to do unseemly things with your interface. If you friend a bunch of classes so they can access private methods, those classes have the ability to do unseemly things with your private implementation details. Both cases embrittle the architecture. What you really want is fine-grained ACLs to class members to document both intent and dependencies.
This method of restricting usage of methods to specific classes at compile time is clever and provides good documentation of design intent, I haven't seen that pattern before. I also would guess that the compiler elides the Badge argument since it is never used.
> With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody.
Essentially, a bugfix that prevents CPU overheating breaks someone's workflow involving a temperature sensor (jokingly).
typedef struct foo_struct *foo;
void foo_frobnicate(foo, int how);
The programmers who use this cannot just edit a header file to gain access to something; the don't have a header file which tells them anything. They could reverse engineer the data structure, but to thwart that, you could scramble the order of the structure members with each new release of the component, so their hack wouldn't be backward or forward compatible.
I think you could also solve this specific problem with an internal header file in c++ too (by moving register/deregister to it's own class) but this solution solves other problems like binary compatibility.
It's also zero width, so no temporaries, etc.
A few bytes of stack is the least of my concerns on some file system device registration function that is called five times when the system boots.
If we imagine a software organization "going to town" with this badge approach so that there are badges all over the code base, it's not hard to imagine how it would be a nuisance.
They're supposed to trigger a reconsideration of the API when a new developer runs into a restriction, but more often in my experience the new developer will just add a new public interface.
Flipping a "private:" to "public:" has no effect on the binary compatibility.
That's not the case on Windows. The access qualifier is part of the mangled name. https://en.wikiversity.org/wiki/Visual_C%2B%2B_name_mangling...
Of course you can get around if you really, really want to. But I think this subthread is starting to split hairs.