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

Reply via email to