Unlike class templates, which can have explicit specializations and partial specializations, function templates do not have the concept of “partial specializations”; they only have explicit specializations and overloads.
Description of function templates in the C++ standard:
A function template defines an unbounded set of related functions.
What is the difference between specialization and function overloading?
**[TC++PL4th]**How does a specialization differ from overloading? From a technical point of view, they differ because individual functions take part in overloading whereas only the primary template takes part in specialization.
The specialization of function templates is slightly different from ordinary function overloading:
1 |
|
Here, void func(int)
is function overloading, not function template specialization (although function specialization functions are also overloaded functions in essence). Note the following issues:
1 | int ival=123; |
From an intermediate code (LLVM-IR) perspective, this is more intuitive:
1 | %1 = alloca i32, align 4 |
The reason is that func<int>(ival)
explicitly generates an overloaded func instance through the function template, while the function called with void func(int)
is different due to the fact that ordinary functions and function templates have two different signature rules:
<function>
name, parameter type list (8.3.5), and enclosing namespace (if any)<function template>
name, parameter type list (8.3.5), enclosing namespace (if any), return type, and template parameter list<function template specialization>
signature of the template of which it is a specialization and its template arguments (whether explicitly specified or deduced)
The C++ standard provides a more direct description:
A non-template function is not related to a function template (i.e., it is never considered to be a specialization), even if it has the same name and type as a potentially generated function template specialization.
That is, declarations of non-template functions do not merely guide overload resolution of function template specializations with the same name. If such a non-template function is odr-used (3.2) in a program, it must be defined; it will not be implicitly instantiated using the function template definition.
About overload resolution:
A function template can be overloaded either by (non-template) functions of its name or by (other) function templates of the same name.
The best viable function resolution for function overloading has a very complex rule, which will not be discussed in this article.
Function specialization has limited functionality and is useful for matching zero-argument functions:
1 | template <typename T> |
Moreover, two different function templates can specialize to the same type:
It is possible to overload function templates so that two different function template specializations have the same type.
1 | // file1.cc |
And:
1 | // file2.cc |
Such specializations do not violate ODR:
Such specializations are distinct functions and do not violate the one definition rule (3.2).
The reason is that the signature rules of function templates include the parameter type list
.
Thus, void f(T*)
and void func(T)
are functions with different signatures:
- The parameter type list for
void func(T*)
is T, and the function parameter is T* - The parameter type list for
void func(T)
is T*, and the parameter type is also T*
You can look at the IR code of the above:
1 | // file1.cc |
Using an intuitive diff view:
It can be seen that although two different function templates can specialize to functions that receive the same parameters, essentially they are still different.