Template Specialization and Argument Deduction
Before exploring the underlying implementation of std::function, there are a couple of things that need to be illustrated about templates.
In previous chapter, we have already known about template specialization. In the following example, we provide a specialized template function for type const char * which uses strcmp() to compare two strings instead of operator >
.
It is similar in class templates. In the following example, we provide a specialized template class for type char *. And initialization of object with type Test<char *> will call the specialized constructor.
This kind of template specialization is called an explicit (or full) template specialization, in which the type inside the brackets should match the specialized template exactly. Now let's look at another example. Here we want all the pointer types to behavior differently than normal types. Then we can write another specialized template class as follow:
The above template class matches any type in form as T *. So if we initialize an object of type Test<int *>, the constructor of our newly written class will be called. This kind of template specialization is called a partial template specialization. Notice that char * is also of type T *, but the explicit template class's constructor is called. Therefore, explicit template class has a higher priority than partial template specialization.
Partial template specialization can also be used to match a function pointer type. In the following example, we have a specialized template class with a function pointer with two parameters and one return value:
Notice that a function pointer type is not the same as a function type. Remember in std::function, the template type should be a function. We can define another specialized class with function type:
We also learnt another feature of templates which is called the template argument deduction. In some cases we don't need to explicitly state the types with brackets, the compiler can deduce the template parameter types from the argument types. In the following example, func1 with different types of parameters are called according to the arguments we pass in.
With partial specialization and argument deduction, templates can achieve more powerful functionalities. In the previous example, func1(sum) is deducted into a function pointer type int (*)(int, int). But with partial specialization, we can separate parameter types and return type apart:
We can also use this feature to deal with member functions. Compared to normal function pointers, member function pointers have a class scope, so we also need to have the class name as template parameter:
In the next article, we will look at how template specialization and argument deduction are used in implementing std::function.
Last updated