Well, that's a problem in the C++ type system, isn't it; because it (effectively) constructs a value of type Badge<Device>, even though it's not a piece of code sitting in the Device class scope.
The rule should be that if the default constructor of T is not accessible in the scope, then any cast to T * or T & requires a diagnostic. Or something like that.
If I can allocate a suitably aligned buffer of sizeof (T) zeros, and then treat that as a T, I've effectively constructed a T.
No, that's a good feature of the C++ type system, because it (effectively) allows the programmer to construct a value of type Badge<Device>, even if Device thinks it's okay to prevent that.
It would be better to do eg "return Device::private:get_badge()", but C++ defectively doesn't support that.
The rule should be that if the default constructor of T is not accessible in the scope, then any cast to T * or T & requires a diagnostic. Or something like that.
If I can allocate a suitably aligned buffer of sizeof (T) zeros, and then treat that as a T, I've effectively constructed a T.