template-template-parameter deducation failed for template method (although explicitly-specialized)
<p>I am attempting to write a small script interpreter that is extensible via c++. For that purpose function handlers are inserted into a dispatch table.
To simplyfy my question, the handlertype is defined as follows (in the real code, this contains parameters for an argument-list and return type):</p>

<pre><code>// Handler type
using function_type = void(int);
</code></pre>

<p>The dispatch table, for now, is a simple unordered map with a (kind of) mangled name as key to implement overloading:</p>

<pre><code>// Dispatch table
std::unordered_map&lt;std::string, function_type*&gt; fn_handlers;
</code></pre>

<p>Methods are added to this table either direct, e.g. like a simple method that takes two arguments of type <code>int</code> (<code>operator+ii</code> is the manged name for this in my case):</p>

<pre><code>fn_handlers["operator+ii"] = my_add_handler;
</code></pre>

<p>However, many handlers, especially those related to basic math, do accept a variety of arguments, all combinations of <code>int</code> and <code>double</code> would be valid, yielding to 4 methods and 4 dispatch table entries. Therefore I decided to implement those methods using templates.
To give an example, this might be basically this (again simplyfied):</p>

<pre><code>template&lt;class A, class B&gt;
void my_add_handler(int /* simplified... */)
{
  // Something here A and B are needed
}
</code></pre>

<p>The dispatch table then is filled like this:</p>

<pre><code>fn_handlers["operator+ii"] = my_add_handler&lt;int,int&gt;;
fn_handlers["operator+di"] = my_add_handler&lt;double,int&gt;;
fn_handlers["operator+id"] = my_add_handler&lt;int,double&gt;;
fn_handlers["operator+dd"] = my_add_handler&lt;double,double&gt;;
</code></pre>

<p>Still a lot to type, but this is okay for now. Anyway since there is obviously a correlation between the template parameters and the method signature (mangled name), I attempted to automate this that you could write (parameter name mangeling would be done inside handler_provider::add):</p>

<pre><code>handler_provider&lt;int, int&gt;::add&lt;my_add_handler&gt;("operator+");
handler_provider&lt;double, int&gt;::add&lt;fn_add_handler&gt;("operator+");
handler_provider&lt;int, double&gt;::add&lt;fn_add_handler&gt;("operator+");
handler_provider&lt;double, double&gt;::add&lt;fn_add_handler&gt;("operator+");
</code></pre>

<p>Which then would take the arguments at the beginning and take them as template arguments for the second type (so that would not have to type the <code>&lt;int, int&gt;</code> part twice).</p>

<p>Just for clarification; I am aware of the I would explicitly specialize the <code>my_add_handler</code> template like this:</p>

<pre><code>handler_provider&lt;int, int&gt;::add&lt;my_add_handler&lt;int,int&gt;&gt;("test");
</code></pre>

<p>But it is exactly this duplication that I want to omit (twict the <code>&lt;int,int&gt;</code>).</p>

<p>However, I keep getting errors with the last part. The <code>handler_provider::add</code> method is defined as follows (the parameter name mangeling as mentioned above is left out because it is not the point here and works as expected):</p>

<pre><code>template&lt;class... Ts&gt;
struct handler_provider
{
  // Overload for templates, such as 'test_handler'
  template&lt;template&lt;class...&gt; class F&gt;
  static void add(const std::string name)
  {
    handler_provider&lt;Ts...&gt;::add&lt;F&lt;Ts...&gt;&gt;(name);
  }

  // Overload for non-template (or already specialized) handlers (aka. function pointers)
  template&lt;function_type F&gt;
  static void add(const std::string name)
  {
    fn_handlers[name] = F;
  }
};
</code></pre>

<p>The first overload, as said, is supposed for the exact case I described above, the handler below installs non-template functions and those which are fully specialized.</p>

<p>However, this gives me an error, telling be that the inner template from a call such as shown above cannot be deduced. I did not think that I told the compiler to deduce anything at all, I complete specialized the template arguments in the call (again):</p>

<pre><code>handler_provider&lt;int, int&gt;::add&lt;my_add_handler&gt;("operator+");
</code></pre>

<p>The arguments for the outer variadic template <code>class... Ts</code> are explicitly named <code>&lt;int, int&gt;</code> and the simple argument for the inner template-template is named as <code>my_add_handler</code>. However, the compiler seems to ignore this(?). This is the output I get (gcc 5.4.0 using <code>-std=c++14</code>):</p>

<pre><code>$ g++ -std=c++14 sci_e1.cpp -o sci
sci_e1.cpp: In function ‘int main()’:
sci_e1.cpp:45:55: error: no matching function for call to ‘handler_provider&lt;int, int&gt;::add(const char [5])’
  handler_provider&lt;int, int&gt;::add&lt;my_add_handler&gt;("operator+");
                                                             ^
sci_e1.cpp:17:15: note: candidate: template&lt;template&lt;class ...&gt; class typedef F F&gt; static void handler_provider&lt;Ts&gt;::add(std::__cxx11::string) [with F = F; Ts = {int, int}]
  static void add(const std::string name)
              ^
sci_e1.cpp:17:15: note:   template argument deduction/substitution failed:
sci_e1.cpp:24:15: note: candidate: template&lt;void (* F)(int)&gt; static void handler_provider&lt;Ts&gt;::add(std::__cxx11::string) [with void (* F)(int) = F; Ts = {int, int}]
  static void add(const std::string name)
              ^
sci_e1.cpp:24:15: note:   template argument deduction/substitution failed:
sci_e1.cpp:45:55: error: could not convert template argument ‘my_add_handler’ to ‘void (*)(int)’
  handler_provider&lt;int, int&gt;::add&lt;my_add_handler&gt;("operator+");
                                                             ^
</code></pre>

<p>I get the second error, thats completly okay and should not be a problem as this overload should be kicked out of overload resolution for template types. The first error is the one that drives me crazy.</p>

<p>Clang (3.9.0) is a little more precise:</p>

<pre><code>$ clang++ -std=c++14 sci_e1.cpp -o sci
sci_e1.cpp:45:3: error: no matching function for call to 'add'
  handler_provider&lt;int, int&gt;::add&lt;my_add_handler&gt;("test");
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sci_e1.cpp:17:15: note: candidate template ignored: invalid explicitly-specified argument for
      template parameter 'F'
  static void add(const std::string name)
              ^
sci_e1.cpp:24:15: note: candidate template ignored: invalid explicitly-specified argument for
      template parameter 'F'
  static void add(const std::string name)
              ^
1 error generated.
</code></pre>

<p>But I still do not understand where I am wrong here. What am I missing?</p>

<p>Thanks,</p>

<p>Sebastian</p>

<hr>

<p>For better testing, here is an full example:</p>

<pre><code>#include &lt;unordered_map&gt;
#include &lt;string&gt;
#include &lt;iostream&gt;

// Handler type
using function_type = void(int);

// Dispatch table
std::unordered_map&lt;std::string, function_type*&gt; fn_handlers;

// Handler provider (to install new handlers)
template&lt;class... Ts&gt;
struct handler_provider
{
  // Overload for templates, such as 'test_handler'
  template&lt;template&lt;class...&gt; class F&gt;
  static void add(const std::string name)
  {
    handler_provider&lt;Ts...&gt;::add&lt;F&lt;Ts...&gt;&gt;(name);
  }

  // Overload for non-template (or already specialized) handlers (aka. function pointers)
  template&lt;function_type F&gt;
  static void add(const std::string name)
  {
    fn_handlers[name] = F;
  }
};


template&lt;class A, class B&gt;
void test_handler(int v)
{
  // Something here A and B are needed
}

void other_handler(int v)
{
  // A handler without specialization
}

int main()
{
  // Install handlers
  handler_provider&lt;int, int&gt;::add&lt;test_handler&gt;("testii");
  handler_provider&lt;double, int&gt;::add&lt;test_handler&gt;("testdi");
  handler_provider&lt;bool, bool, int&gt;::add&lt;other_handler&gt;("otherbbi");

  // Dispatch
  fn_handlers["testii"](5); // Sould call test_handler&lt;int, int&gt;
  fn_handlers["testdi"](5); // Should call test_handler&lt;double, int&gt;

  fn_handlers["otherbbi"](5); // Should call other_handler
}
</code></pre>