In C, the way to do PIMPL is to write just a struct declaration:
=== s.h ===
struct S;
=== s.c ===
#include "s.h"
struct S { ... };
=== t.c ===
#include "s.h"
struct T {
S* pimpl;
};
And the users of T cannot access anything in S. The straightforward equivalent
in D is:
=== s.di ===
struct S;
=== s.d ===
struct S { ... }
=== t.d ===
import s;
struct T {
S* pimpl;
};
But if you don't want to use .di files, such as when compiling all the files
together with one command, then things get a bit awkward. D doesn't like:
=== s.d ===
public struct S;
private struct S { ... }
Making a public alias to a private struct doesn't work, as the struct's members
are still accessible. I finally found a way:
=== s.d ===
public struct Spimpl {
private S* pimpl;
private alias pimpl this;
}
private struct S { ... }
=== t.d ===
import s;
struct T {
Spimpl* s;
}
and the contents of S are inaccessible to T, while type safety is maintained.
There are no extra indirections - the alias this takes care of that. s.d can use
s to directly access S's contents, but t.d cannot.
https://github.com/dlang/dmd/blob/master/src/dmd/func.d#L229
https://github.com/dlang/dmd/blob/master/src/dmd/dinterpret.d#L151
C: http://wiki.c2.com/?PimplIdiom
C++: http://en.cppreference.com/w/cpp/language/pimpl