title: C++ CRTP based dataflow output class design simplification
body: <hr>
  
  <p><strong>Background information</strong></p>
  
  <p>I am working on a dataflow-like design pattern. The classes presented below are meant to represent the output data dispatch mechanism. <code>level1</code> is a CRTP base class. <code>getOutput&lt;N&gt;</code> in <code>level1</code> is the function that can be used for getting the output data from an instance of a derived class. Depending on the template parameter <code>N</code> it calls one of the user defined methods <code>getOutputImpl</code>. These methods are meant to be provided in a (CRTP-style) derived class. Each of the methods <code>getOutputImpl</code> defines an output port associated with the user defined derived class. The input type of the method <code>getOutputImpl</code> is defined by design. The output types of the methods <code>getOutputImpl</code> can vary. However, by design, the output type must have a structure <code>std::unique_ptr&lt;TOutputType&gt;</code>, where TOutputType can be any class. More background information can be found here: <a href="https://stackoverflow.com/questions/29843398/c-partial-template-specialization-design-simplification">previous question</a>. </p>
  
  <hr>
  
  <p><strong>Question</strong></p>
  
  <p>To allow for automatic recognition of the number of the user defined ports (i.e. methods <code>getOutputImpl</code>) a method <code>getOutputPortsNumber(void)</code> is provided in the base <code>level1</code> class. This method is based around the idea that the return type of all user defined methods <code>getOutputImpl</code> is <code>std::unique_ptr&lt;TOutputType&gt;</code>. Thus, one can define an additional <code>getOutputImpl</code> method in the base class that does not have this return type (e.g. it has a <code>void</code> return type: <code>void getOutputImpl(...)</code>). </p>
  
  <p>The methodology described above works if the <code>void getOutputImpl(...)</code> is defined within the user-defined derived class (<code>DataflowOutputClass</code> in this example) along with other user-defined <code>std::unique_ptr&lt;TOutputType&gt; getOutputImpl(...)</code> methods. However, when the additional <code>void getOutputImpl(...)</code> method is moved to the base <code>level1</code> class, I get a compilation error: <code>no matching function for call to 'DataflowOutputClass&lt;int&gt;::getOutputImpl(PortIdxType&lt;2ul&gt;, const PolyIndex&amp;) const</code>.</p>
  
  <hr>
  
  <p><strong>Code</strong></p>
  
  <pre><code>typedef size_t Index;
  typedef unsigned long Natural;
  typedef std::vector&lt;Index&gt; PolyIndex;
  typedef const PolyIndex&amp; crPolyIndex;
  template&lt;Index N&gt; struct PortIdxType{};
  
  template&lt;typename TLeafType&gt;
  class level1
  {
  
  public:
  
      TLeafType* asLeaf(void)
          {return static_cast&lt;TLeafType*&gt;(this);}
  
      TLeafType const* asLeaf(void) const
          {return static_cast&lt;TLeafType const*&gt;(this);}
  
      template &lt;Index N&gt;
      auto getOutput(crPolyIndex c_Idx) const
          {return asLeaf() -&gt; getOutputImpl(PortIdxType&lt;N&gt;{}, c_Idx);}
  
      static constexpr Natural getOutputPortsNumber(void)
          {return getOutputPortsNumberImpl&lt;0&gt;();}
  
      template&lt;Index N&gt;
      static constexpr std::enable_if_t&lt;
          std::is_void&lt;
              decltype(
                  std::declval&lt;TLeafType*&gt;() -&gt;
                  getOutput&lt;N&gt;(PolyIndex({}))
                  )
          &gt;::value,
              Index
              &gt; getOutputPortsNumberImpl(void)
          {return N;}
  
      template&lt;Index N&gt;
      static constexpr std::enable_if_t&lt;
          !std::is_void&lt;
              decltype(
                  std::declval&lt;TLeafType*&gt;() -&gt;
                  getOutput&lt;N&gt;(PolyIndex({}))
                  )
          &gt;::value,
              Index
              &gt; getOutputPortsNumberImpl(void)
          {return getOutputPortsNumberImpl&lt;N + 1&gt;();}
  
      template&lt;Index N&gt;
      void getOutputImpl(
          PortIdxType&lt;N&gt;, crPolyIndex c_Idx
          ) const
          {throw std::runtime_error("Wrong template argument.");}
  
  
  };
  
  template&lt;typename T&gt;
  class DataflowOutputClass:
      public level1&lt;DataflowOutputClass&lt;T&gt;&gt;
  {
  public:
  
      // if void getOutputImpl(...) const is moved here from level1,
      // then the code compiles and works correctly.
  
      //overload for when N = 0
      std::unique_ptr&lt;double&gt; getOutputImpl(
          PortIdxType&lt;0&gt;, crPolyIndex c_Idx
          ) const
      {
          std::unique_ptr&lt;double&gt; mydouble(new double(10));
          return mydouble;
      }
  
      //overload for when N = 1
      std::unique_ptr&lt;int&gt; getOutputImpl(
          PortIdxType&lt;1&gt;, crPolyIndex c_Idx
          ) const
      {
          std::unique_ptr&lt;int&gt; myint(new int(3));
          return myint;
      }
  
  };
  
  
  int main()
  {
      DataflowOutputClass&lt;int&gt; a;
      std::cout &lt;&lt; a.getOutputPortsNumber() &lt;&lt; std::endl;
  }
  </code></pre>