I haven't read this whole back-and-forth, but I totally
understand where iesvs is coming from here. I've often wished
I could declare just the public part of a class in a header,
and the private part elsewhere. And there's no deep reason I
shouldn't be able to do that; it's just a missing language
feature.
In a way, yes. On the other hand, supporting this would create
very serious implementation problems. Perhaps if you find a
reasonable way to implement it, it could be adopted; at present,
the best compiler experts I know don't consider it implementable
(while still allowing value semantics, of course).
C++ already supports incomplete struct/class types, which
correspond to the special case where everything is hidden. It
could just as well support partially complete types.
If they had the same restrictions as incomplete types, maybe.
But then, you'd need to define a special syntax, etc., to define
them. And what does it buy you? What can you do with them that
you can't already do with incomplete types.
I can even think of a reasonably intuitive syntax for it that
doesn't require any new keywords:
// header
class A {
public:
float f;
void method();
... // <- that's a literal '...'
};
// private implementation
class A : public Base {
public:
float f; // must match (enforced by implementation)
void method();
private:
int x;
};
The current syntax "class A;" would be identical to "class A { ... };".
I suspect, though, that if I proposed this to the standards
committee, they'd say "use virtual functions". And indeed you
can get exactly the same effect with virtual functions:
class A {
public:
float f;
virtual void method() = 0;
};
// private implementation
class A_impl : public A, public Base {
public:
void method();
private:
int x;
};
void A_impl::method() { ... }
Exactly.
Note that if you allow declaring instances of the "partially
complete" class A, you run into serious implementation problems.
And if you don't, your partially complete class doesn't provide
any advantage with respect to the above.
So this is what I recommend to the original poster. As far as
I can tell, it does exactly what you want. The only advantage
of incomplete class declarations would be efficiency: in a
typical implementation they'd save you a machine word per
object and a hard-to-predict indirect jump per method call.
And the compilation firewall idiom allows replacing the virtual
function call with a non-virtual one (but imposes an additional
indirection on the data accesses, or a second function call).
This is, perhaps, the reason why C++ does things the way it
does. You, as programmer, choose the compromize; it's not
forced on you by the language. For large, complex objects,
where the compile time dependencies are an issue, you use either
an abstract base class or the compilation firewall idiom. For
simple, time critical values (e.g. things like std::complex),
you declare the private members in the header, so that the
compiler can optimize their use. You have the choice; it isn't
imposed on you by the language.