title: Type specialization at compile-time
body: <p>I'm writing a class which shares several different features with <code>std::function</code> (or at least the classes are in many ways similar). As you all know <code>std::function</code> is instantiated by specifying the template parameters (i.e <code>std::function&lt;void (std::string&amp;)&gt;</code>), it is the same for my class. I have an exception though, I want to specialize a <em>single</em> function in my class, if the return value is void (<code>std::function&lt;"return value" ("parameters"&gt;</code>). I need this to be done at compile time, and I just can't make it work as it should. Here is some test code for explanation:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;type_traits&gt;
  
  template &lt;typename T&gt; class Test { };
  
  template &lt;typename Ret, typename... Args&gt;
  class Test&lt;Ret (Args...)&gt;
  {
  public:
      Ret operator()(Args...)
      {
          if(std::is_void&lt;Ret&gt;::value)
          {
               // Do something...
          }
  
          else /* Not a void function */
          {
              Ret returnVal;
              return returnVal;
          }
      }
  };
  
  int main(int argc, char * argv[])
  {
      Test&lt;void (char)&gt; test;
      test('k');
  }
  </code></pre>
  
  <p>As you can clearly see, if the compiler does not remove the 'else' branch in the above test, my code will try to create a void value (i.e <code>void returnVal;</code>). The problem is that the compiler does not remove the branch so I end up with a compiler error:</p>
  
  <blockquote>
    <p>./test.cpp: In instantiation of ‘Ret Test::operator()(Args ...) [with Ret = void; Args = {char}]’:
    ./test.cpp:27:10:   required from here ./test.cpp:18:8: error:
    variable or field ‘returnVal’ declared void ./test.cpp:19:11: error:
    return-statement with a value, in function returning 'void'
    [-fpermissive]</p>
  </blockquote>
  
  <p>One would normally use <code>std::enable_if</code> combined with <code>std::is_void</code>, the problem is that I don't want to specialize on the <em>function</em> template, but on the <em>class</em> template.</p>
  
  <pre><code>template &lt;typename Ret, typename... Args&gt;
  class Test&lt;Ret (Args...)&gt;
  {
  public:
      typename std::enable_if&lt;!std::is_void&lt;Ret&gt;::value, Ret&gt;::type 
      Ret operator()(Args...)
      {
          Ret returnVal;
          return returnVal;
      }
  
      typename std::enable_if&lt;std::is_void&lt;Ret&gt;::value, Ret&gt;::type 
      Ret operator()(Args...)
      {
          // It's a void function
          // ...
      }
  };
  </code></pre>
  
  <p>If I use the above code instead I end up with even more errors and without a solution</p>
  
  <pre><code>./test.cpp:11:2: error: expected ‘;’ at end of member declaration
  ./test.cpp:11:2: error: declaration of ‘typename std::enable_if&lt;(! std::is_void&lt;_Tp&gt;::value), Ret&gt;::type Test&lt;Ret(Args ...)&gt;::Ret’
  ./test.cpp:6:11: error:  shadows template parm ‘class Ret’
  ./test.cpp:11:24: error: ISO C++ forbids declaration of ‘operator()’ with no type [-fpermissive]
  ./test.cpp:18:2: error: expected ‘;’ at end of member declaration
  ./test.cpp:18:2: error: declaration of ‘typename std::enable_if&lt;std::is_void&lt;_Tp&gt;::value, Ret&gt;::type Test&lt;Ret(Args ...)&gt;::Ret’
  ./test.cpp:6:11: error:  shadows template parm ‘class Ret’
  ./test.cpp:18:24: error: ISO C++ forbids declaration of ‘operator()’ with no type [-fpermissive]
  ./test.cpp:18:6: error: ‘int Test&lt;Ret(Args ...)&gt;::operator()(Args ...)’ cannot be overloaded
  ./test.cpp:11:6: error: with ‘int Test&lt;Ret(Args ...)&gt;::operator()(Args ...)’
  ./test.cpp: In member function ‘int Test&lt;Ret(Args ...)&gt;::operator()(Args ...)’:
  ./test.cpp:22:2: warning: no return statement in function returning non-void [-Wreturn-type]
  ./test.cpp: In instantiation of ‘int Test&lt;Ret(Args ...)&gt;::operator()(Args ...) [with Ret = void; Args = {char}]’:
  ./test.cpp:28:10:   required from here
  ./test.cpp:13:7: error: variable or field ‘returnVal’ declared void
  ./test.cpp: In member function ‘int Test&lt;Ret(Args ...)&gt;::operator()(Args ...) [with Ret = void; Args = {char}]’:
  ./test.cpp:15:2: warning: control reaches end of non-void function [-Wreturn-type]
  </code></pre>
  
  <p>I'm sorry if I'm just plain dumb, and the answer is obvious. I'm fairly new to templates and I couldn't find a suiting answer in any of the other threads/questions.</p>