Consider the following function template with explicit specializations.
template<typename T>
void f(T);
template<>
void f<int>(int i) { std::cout << "f() chose int\n"; ++i; }
template<>
void f<const int&>(const int&) { std::cout << "f() chose const int&\n"; }
The first specialization can be implicitly instantiated. The second cannot, even if the first specialization is absent. This is unlike the rules for function overloading where a function taking int
or const int&
works fine (g()
in linked examples).
Example with a specialization for int
available. Works.
http://coliru.stacked-crooked.com/a/1680748749f36631
Example with only a specialization for const int&
available. Compiles but fails to link.
http://coliru.stacked-crooked.com/a/ab8b068d3f807837
Why does template type deduction work this way and why was it chosen to work this way? The alternative would be for template type deduction to behave like function overloading.
My understanding is that with overloaded functions, the compiler already knows all the available options but with templates the compiler must first decide what to look for and then see if it can be instantiated. If this is the case, then would requiring the compiler to search for qualified variations on types be an unreasonable demand?
Consider the case of no explicit specializations:
template <typename T>
void f(T x)
{
T y = 42 + x;
std::cout << y;
}
int main()
{
int n = 1337;
f(n);
}
Template argument deduction never deduces a reference type, because the alternative would be to always deduce a reference type. If it did, the above call to f(n)
would call f<int&>
, which would make T y = 42 + x;
ill-formed.
Picking a specialization happens after deduction is complete.
The first specialization can be implicitly instantiated. The second cannot, even if the first specialization is absent.
You can't make f<int>
absent, you declared it here:
template<typename T>
void f(T);