C++ template Partial Specialization Member Function; Am I doing right?
What you've written does work, and you seem to understand all the concepts (e.g., "you can't partially specialize function templates"), and your coding style (indentation and whatnot) seems fine.



Well, one coding-style improvement: You need those (void)input casts to shut up compiler warnings about unused parameters... in C. But in C++ you don't need those casts; what you do instead is, if you're not going to use a parameter, just don't give it a name.

static void bar(const T&amp;) { ... }




However, your code doesn't really match any common TMP patterns — which is probably just because you're noodling around, learning, instead of trying to solve a specific problem.

If you just wanted to produce the same output with less code, you would do this:

struct Foo
{
    template&lt;class T&gt; auto bar(const T&amp;) -&gt; std::enable_if_t&lt;!std::is_integral&lt;T&gt;::value&gt;
    {
        std::cout &lt;&lt; "Generic" &lt;&lt; std::endl;
    }

    template&lt;class T&gt; auto bar(const T&amp;) -&gt; std::enable_if_t&lt;std::is_integral&lt;T&gt;::value&gt;
    {
        std::cout &lt;&lt; "Specialization for integral type" &lt;&lt; std::endl;
    }

    void bar(bool)
    {
        std::cout &lt;&lt; "Specialization for bool" &lt;&lt; std::endl;
    }

    void bar(const std::string&amp;)
    {
        std::cout &lt;&lt; "Specialization for std::string" &lt;&lt; std::endl;
    }
};

int main()
{
    Foo foo;
    foo.bar(Foo());
    foo.bar(std::string());
    foo.bar(bool());
    foo.bar(int());
    return 0;
}


That is, your code is equivalent to providing two overloads of foo.bar, plus a couple of mutually exclusive templates (one for integral types and one for other types). The specific overloads for bool and std::string will take precedence over the templates.



Alternatively, you could use tag dispatch, as follows. (But I don't recommend it in this case because it turns out to be surprisingly subtle. Replace the second instance of std::true_type with ... and watch that overload silently drop out. I'm not actually sure why.)

struct Foo
{
    template&lt;class T&gt; void bar_impl(const T&amp;, ...) {
        std::cout &lt;&lt; "Generic" &lt;&lt; std::endl;
    }

    template&lt;class T&gt; void bar_impl(const T&amp;, std::true_type) {
        std::cout &lt;&lt; "Specialization for integral type" &lt;&lt; std::endl;
    }

    void bar_impl(const std::string&amp;, ...) {
        std::cout &lt;&lt; "Specialization for std::string" &lt;&lt; std::endl;
    }

    void bar_impl(const bool&amp;, std::true_type) {
        std::cout &lt;&lt; "Specialization for bool" &lt;&lt; std::endl;
    }

    template&lt;class T&gt; void bar(const T&amp; input)
    {
        bar_impl(input, std::is_integral&lt;T&gt;{});
    }
};




Maybe the best approach would be to use two non-interacting levels of tag dispatch: first, is T integral? and second, what is T exactly?

template&lt;bool IsIntegral&gt; struct BarImpl {
    template&lt;class T&gt; static void bar(const T&amp;) {
        std::cout &lt;&lt; "Generic" &lt;&lt; std::endl;
    }
    static void bar(const std::string&amp;) {
        std::cout &lt;&lt; "Specialization for std::string" &lt;&lt; std::endl;
    }
};

template&lt;&gt; struct BarImpl&lt;true&gt; {
    template&lt;class T&gt; static void bar(const T&amp;) {
        std::cout &lt;&lt; "Specialization for integral type" &lt;&lt; std::endl;
    }
    static void bar(bool) {
        std::cout &lt;&lt; "Specialization for bool" &lt;&lt; std::endl;
    }
};

struct Foo {
    template&lt;class T&gt; void bar(const T&amp; input) {
        BarImpl&lt;std::is_integral&lt;T&gt;::value&gt;::bar(input);
    }
};