Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deduce template parameter in explicit specialization of function template?

Consider following case:

#include <iostream>

template <class T> void f(T) { std::cout << "#1\n"; } // #1
template <> void f(const int) { std::cout << "#2\n"; } // #2

int main() {
    f<const int>(1); // call #1
    f<int>(1);       // call #2
    return 0;
}

It seems #2 is f<int>(const int) instead of f<const int>(const int). What happens here? My first thought was top level const is discarded in function type transformation, so that the type of #2 is void(int), which results in a specialization of f<int>(const int). But I'm not sure about that.

And why C++ allows such syntax? I mean since we can't partial specialize function templates, we would have known the template argument value if we want to explicitly specialize one. So why C++ don't just force programmer explicitly provides template argument values when specializing template functions? (i.e. we would have to write specialization of #1 in template <> void f<int>(const int) { } or template <> void f<int const>(const int) { }) Does it have special usage except for coding convenience?

like image 530
Carousel Avatar asked Aug 25 '16 15:08

Carousel


1 Answers

void f(const int p)

Setting aside the issue of templates, for the moment, the const part here does not specify the type of the parameter to f(). All that const here specifies is that p is const inside the function f(). The type of the parameter to f() is int.

template <> void f(const int)

When the compiler is trying to deduce the type of the specialization, it deduces that since the function parameter's type is int, this must be a specialization for f<int>.

Can't really make deduction work this way. You have to be explicit, if that's what you want to do:

template <> void f<const int>(const int) { std::cout << "#2\n"; }
like image 132
Sam Varshavchik Avatar answered Nov 10 '22 05:11

Sam Varshavchik