Template explicit vs implicit specialization

Short answer: top-level const on a by-value parameter is not part of a function’s type, so template<> void f(const int) is the explicit specialization of f<int>. Calling f with an int (const or not) runs the specialization. Any other argument type falls back to an implicit instantiation of the primary template.

    #include <iostream>
    using std::cout;

    // Main template
    template<class T>
    void f(T n) {
        cout << 2;
    }
    // Template specialization
    template<>
    void f(const int n) {
        cout << 1;
    }

    int main() {
        int n = 11;
        f(n);
    }

Code outputs 1.

For the function call f(n), since ‘n’ is of int type, the template argument T is deduced as T = int.

The explicit specialization

 template<> void f(const int n)

looks like it is for const int, but when a function type is formed the top-level const on a by-value parameter is dropped. Its signature is void(int), so it is the specialization for T = int and it is the one that runs.

The const still matters inside the body: n cannot be modified there. It just doesn’t change which calls match.

Passing a const int also outputs 1, because template argument deduction drops top-level const from a by-value argument too (T = int).

To see the primary template, call f with a different type: f(2.0) deduces T = double, no specialization exists for it, so the compiler implicitly instantiates f<double> and the code outputs 2.

Explicit specializations do not take part in overload resolution. The compiler first picks the best primary template for the call (deducing T), and only then checks whether an explicit specialization exists for those exact template arguments. If one does, it is used; otherwise the primary template is implicitly instantiated.