C++ Quiz121 of 173
Difficulty:
⬅️ Prev: 250Quiz ID: 251Next: 252 ➡️

According to the C++23 standard, what is the output of this program?

#include <iostream>

template<class T>
void f(T) { std::cout << 1; }

template<>
void f<>(int*) { std::cout << 2; }

template<class T>
void f(T*) { std::cout << 3; }

int main() {
    int *p = nullptr;
    f( p );
}
Hint

A declaration of a function template being explicitly specialized shall precede the declaration of the explicit specialization. During overload resolution, only the base function templates are considered, not specializations.

Reveal answer

3

Explanation

The name f is overloaded by the two function templates void f(T) and void f(T*). Note that overload resolution only considers the function templates, not the explicit specialization void f<>(int*)! For overload resolution, first we deduce the template arguments for each function template, and get T = int * for the first one, and T = int for the second.

Both function templates are viable, but which one is best? According to §[over.match.best]¶2, a function template is a better match than another function template if it's more specialized:

(...) a viable function F1 is defined to be a better function than another viable function F2 if (...) the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in §[temp.func.order] (...)

The process of partial ordering is a bit long to quote here, and not key to this question. But in summary, anything accepted by f(T*) would also be accepted by f(T), but not the other way around. So f(T*) is more specialized.

Now we know that the function template void f(T*) is selected by overload resolution, and we can start thinking about specializations. Which of the function templates is void f<>(int*) a specialization of? §[temp.expl.spec]¶4:

A declaration of a function template (...) being explicitly specialized shall be reachable from the declaration of the explicit specialization.

So the explicit specialization void f<>(int*) is a specialization of void f(T), since that's the only function template declaration that precedes it. Overload resolution however selected the other function template, void f(T*), and we instead call an implicitly instantiated specialization of that, printing 3.

Note: This example is taken from Why Not Specialize Function Templates? by Herb Sutter.

⬅️ Prev: 250Quiz ID: 251Next: 252 ➡️