title: Curiously Recurring Template Pattern -- Inheritance and friends
body: <h2>Intro</h2>
  
  <p>I am trying to use the Curiously Recurring Template Pattern to make things storable in hdf5 groups.
  But I have two problems:</p>
  
  <ol>
  <li>How to make the member implementation private?</li>
  <li>How to use the CRTP with namespaces?</li>
  </ol>
  
  <h2>What I want</h2>
  
  <p>(The code follows) <code>hdf5::Group</code> represents an hdf5 group, and can store datasets.<code>hdf5::Storable</code> is a CRTP template class. The function <code>hdf5::store</code> should take a group and a storable object and call the object's implementation. All these should be inside the namespace <code>hdf5</code> to keep things clean.</p>
  
  <p><code>A</code> implements a storable. It lives outside the <code>hdf5</code> namespace (e.g. global, or another namespace). The implementation method <code>A::store</code> should be private, to make sure that everyone uses <code>hdf5::store</code> instead.</p>
  
  <h2>What I have</h2>
  
  <p>The parts in question have comments pointing out the problems.</p>
  
  <pre><code>#include &lt;string&gt;
  #include &lt;iostream&gt;
  
  namespace hdf5 {
  
  /// A group can contain other groups, and datasets.
  class Group {
  public:
      /// Create a group under a parent group.
      Group(Group* parent, const std::string &amp;name)
          : parent_(parent), name_(name)
      {
          std::cout &lt;&lt; "Creating group \"" &lt;&lt; name &lt;&lt; "\"";
          if (parent != nullptr)
              std::cout &lt;&lt; " under \"" &lt;&lt; parent-&gt;name_ &lt;&lt; "\"";
          std::cout  &lt;&lt; "." &lt;&lt; std::endl;
      };
  
      /// Create a root group.
      Group() : Group(nullptr, "root") { }
  
      /// Create a dataset inside.
      void create_dataset(const std::string &amp;name)
      {
          std::cout &lt;&lt; "Creating dataset \"" &lt;&lt; name &lt;&lt; "\""
              &lt;&lt; " under \"" &lt;&lt; name_ &lt;&lt; "\"." &lt;&lt; std::endl;
      }
  
  private:
      Group *parent_;
      std::string name_;
  };
  
  /** Abstraction of a storable class.
   *
   * Curiously recurring template pattern.
   * Makes it possible to write
   *
   *     store(grp, obj);
   *
   */
  template&lt;class Derived&gt;
  class Storable {
      friend void hdf5::store(hdf5::Group &amp;grp, const Derived &amp;obj) {
          obj.store(grp);
      }
  };
  
  }  // namespace hdft
  
  
  /// Some data class that should be storable.
  class A : private hdf5::Storable&lt;A&gt; {
  public:
      A(const std::string &amp;name) : name_(name) { }
  
  /*
   * Why can't I make it private? `store` should be friend.
   *
   *     test.cc: In instantiation of ‘void hdf5::store(hdf5::Group&amp;, const A&amp;)’:
   *     test.cc:104:19:   required from here
   *     test.cc:72:10: error: ‘void A::store(hdf5::Group&amp;) const’ is private
   *          void store(hdf5::Group &amp;grp) const {
   *               ^
   *     test.cc:45:9: error: within this context
   *              obj.store(grp);
   *              ^
   */
  // private:
  public:
      /// Implementation of the storage
      void store(hdf5::Group &amp;grp) const {
          grp.create_dataset(name_);
      }
  
  private:
      std::string name_;
  };
  
  
  /// Demonstration.
  int main(void) {
      hdf5::Group root,
            grpa(&amp;root, std::string("group_a")),
            grpb(&amp;root, std::string("group_b"));
      A a1(std::string("A1")), a2(std::string("A2"));
  
      /*
       * This is what I want, but it doesn't compile:
       *
       *     test.cc: In function ‘int main()’:
       *     test.cc:96:5: error: ‘store’ is not a member of ‘hdf5’
       *          hdf5::store(root, a1);
       *          ^
       */
      // hdf5::store(root, a1);
      // hdf5::store(root, a2);
      // hdf5::store(grpa, a1);
      // hdf5::store(grpb, a2);
  
      /*
       * This OTOH compiles and runs.
       */
      store(root, a1);
      store(root, a2);
      store(grpa, a1);
      store(grpb, a2);
  }
  </code></pre>
  
  <h2>The Expected Output</h2>
  
  <pre><code>Creating group "root".
  Creating group "group_a" under "root".
  Creating group "group_b" under "root".
  Creating dataset "A1" under "root".
  Creating dataset "A2" under "root".
  Creating dataset "A1" under "group_a".
  Creating dataset "A2" under "group_b".
  </code></pre>