template <class T>
void max (T &a ,T &b)
{}//generic template #1
template<> void max(char &c, char &d)
{} //template specializtion #2
void max (char &c, char &d)
{}//ordinary function #3
what is difference between 1 ,2, and 3?
is a template function
is a total specialization of the previous template function (doesn't overload!)
is an overload of the function
Here is an excerpt from C++ Coding Standards: 101 Rules, Guidelines, and Best Practices:
66) Don't specialize function templates
Function template specializations never participate in overloading: Therefore, any specializations you write will not affect which template gets used, and this runs counter to what most people would intuitively expect. After all, if you had written a nontemplate function with the identical signature instead of a function template specialization, the nontemplate function would always be selected because it's always considered to be a better match than a template.
The book advises you to add a level of indirection by implementing the function template in terms of a class template:
#include <algorithm>
template<typename T>
struct max_implementation
{
T& operator() (T& a, T& b)
{
return std::max(a, b);
}
};
template<typename T>
T& max(T& a, T& b)
{
return max_implementation<T>()(a, b);
}
See also:
Why Not Specialize Function Templates?
Template Specialization and Overloading
The matching rules for template parameters subtly differ from that of overloaded functions. An example of what differs can be seen when you try to invoke max() with arguments of different tyoes:
max(1,'2');
This will match the overloaded function, but neither the base template nor the specialization.
Related
This question is more theoretical and the scope is different from :
Template Specialization VS Function Overloading - Explaining that the compiler does overload resolution before it even looks at specializations
Template specialization vs. Function overloading - Describing the difference between the two mechanisms
Let's get into theoretical questions:
template <typename T>
T add(T a, T b)
{
return a + b;
}
template <>
int add<int>(int a, int b)
{
return a + b; //Specialization
}
int add(int a, int b)
{
return a + b; //Overloading
}
add(3,4); // in Main
1. When to use function full specialization and when to use function overloading?
Why to use template specialization since the templates are parsed twice (at template definition and at instantiation)?
On the other hand, in the case of function overloading, the answer seems pretty obvious: use it when you have a specific, particular case that needs a different logic rather than the template generic one.
2. Is the lookup process (for gcc or clang) going to choose every time the overloading candidate instead of the specialization if the form is the same? By form I mean: function name, number of arguments, argument types.
In the case of full function specialization, when the template functions are candidates, the compiler selects the template instances. Some are chosen, based on the accepted conversions (in order: strict exact match, qualification adjustment, inheritance derived to base conversion for virtual).
In the case of function overloading, among the candidate functions, select the viable ones for the call. Among the viable functions, select the best match for the call. Basically, the compiler checks the conversion strength (in order: strict exact match, qualification adjustment, int/float promotions, conversions, user conversions such as cast).
Normally, in case of ambiguity for the best viable between a template (specialization) and a non-template (overloading), the compiler selects the non-template. But why? How does the lookup mechanism work?
One factor might be the fact that the supported conversions are not the same.
Example:
template <typename T>
bool isEqual(const T& a, const T& b); //generic form
template <>
bool isEqual(const string& a, const string& b); //specialization
bool isEqual(const string& a, const string& b); //overloading
bool c = isEqual ("cheers", "noroc"); //in Main, the arguments are const char *
In this case, the specialization does not match since it would require a user-defined conversion const char * -> string which is forbidden in argument deduction context.
On the other hand, the overloading match since the user-defined conversion is valid here.
but what if in Main, we give strings as arguments?
string s1, s2;
bool c = isEqual (s1, s2);
Why does the compiler choose the overloading function in this case?
The most fundamental difference is that overloads are found independently by name lookup, whereas specializations are found through the original template itself. The result is that overloads that appear after the call are found only by ADL:
template<class T> void f(T) {} // #1
template<class T> void g(T t) {f(t);}
void f(int) {} // #2
template<> void f(char) {} // #3
namespace N {
struct A {};
void f(A) {} // #4
}
void h() {
f(1); // calls #2
g(1); // calls #1
g('1'); // calls #3
g(N::A()); // calls #4
}
While overload resolution prefers a function over a function template specialization with the same signature, only an explicit specialization completely prevents implicitly instantiating the primary template (which can be selected otherwise with f<>('a')).
Another important (and the most famous) difference is that overloaded function templates behave very similarly to partial specializations (which are not available for function templates). This extends even to picking the best overload when more than one matches (via partial ordering). Of course, the limitation on name lookup pertains, so this isn’t a good means of expressing customizations that might appear after their usage; the idiomatic way to combine these features (and enable template argument deduction) is to have a “front man” function template that forwards calls to the appropriate specialization of a class template (which might be generated from a partial specialization).
// g++(5.4)
void func(int * const &) {}
void func(int *) {}
template <typename T> void tfunc(const T &) {}
template <typename T> void tfunc(T *) {}
int main()
{
int a = 0;
func(&a); // ambiguous
tfunc(&a); // unambiguous
return 0;
}
According to my another test, tfunc(&a) instantiates the first template to void tfunc(int * const &) which has the same parameter type as the first nontemplate.
So, why is the first call ambiguous but the second not?
Given two function templates that are otherwise equally as good, overload resolution will select the more specialized function template, using a procedure commonly known as partial ordering. The exact rules are pretty complicated, but essentially it tries to determine if the set of arguments template A can be called with is a (proper) subset of the set of arguments template B can be called with. If so, then A is more specialized than B, and overload resolution will prefer A.
Thus, in your case, tfunc(const T&) can be called with ~everything; tfunc(T*) can only be called with pointers. The latter is more specialized, and is therefore selected.
If you are interested in the standardese and detailed rules, see [temp.func.order] and [temp.deduct.partial].
There are some special rules in overload resolution for template functions, one of them is :
F1 and F2 are function template specializations, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.6.2.
See this question about how to determine which function template is more specialized.
Here, as the second template function is more specialized, there is no ambiguation.
#include <iostream>
void func(int * const &) {}
void func(int *) {}
template <typename T> void tfunc(const T &) {std::cout << "#1\n";}
template <typename T>void tfunc(T *) {std::cout << "#2\n";}
int main()
{
int a = 0;
//func(&a); // ambiguous
tfunc(&a); // unambiguous
return 0;
}
// output: #2
Edit: Though a test in https://ideone.com/C9rF8b , we can see that the second template is chosen, not the first one as stated in the question.
Because a const pointer and a non-const pointer (i.e. T * const and T *) makes no difference if they appear in a function's parameters, and so does passing by value (by copy) and passing by const reference. That's the reason why f(&a) is ambiguous.
For the second one, since &a is resolved to int *, the second template matches better because it's more specialized (it can't accept non-pointer arguments). The first template is more general so it's not used.
If you change the first template function to this it will also be ambiguous:
template <typename T>
void tfunc(T * const &) {}
Consider the code:
#include <iostream>
#include <algorithm> // std::swap C++98
#include <utility> // std::swap C++11
namespace A
{
template<typename T>
struct Foo {};
template<typename T>
void swap(Foo<T> &lhs, Foo<T> &rhs)
{
std::cout << "A::swap<T>" << std::endl;
}
} /* end namespace A */
namespace std // we explicitly specialize std::swap here
{
template<> // explicit template specialization for std::swap<int>
void swap(A::Foo<int> &lhs, A::Foo<int> &rhs)
noexcept
(is_nothrow_move_constructible<A::Foo<int>>::value && is_nothrow_move_assignable<A::Foo<int>>::value)
{
std::cout << "std::swap<int>" << std::endl;
}
} /* end namespace std */
int main()
{
using std::swap;
A::Foo<int> a, b;
A::Foo<double> x, y;
swap(a, b); // ADL, expected to call std::swap<Foo<int>>, but NO
swap(x, y); // ADL, expected to call A::swap<T>, YES
}
I would expect the std::swap explicit specialization to be a better candidate in the call swap(a, b), however it seems that the overload A::swap is always preferred, i.e. the output is:
A::swap<T>
A::swap<T>
Can anyone explain why this behaviour?
Function template explicit specializations don't take part in overload resolution. Only function declarations synthesized from primary templates are considered. If one such function is chosen as the best viable function by the overload resolution process, an explicit specialization of the corresponding primary template will be used if suitable.
In this case, overload resolution needs to choose between a function declaration synthesized from your swap function template overload taking foo<T>& and one synthesized from the std::swap primary template taking T&.
None of these two functions can be chosen over the other based on conversions (they have the same function parameters), both are template specializations, so partial ordering of function templates is considered, which yields your swap function template as more specialized, so the function declaration synthesized from your swap overload wins.
Explicit function template specializations never change which function template or overload is called, only the implementation of the template if it is called.
Overload resolution ignore specializations (as opposed to overloads, which can look a lot like partial specialization to someone unfamiliar with C++ function template quirks).
I can imagine why: mixing both overload and template specialization selection rules would make the rules even harder to follow and get right.
In general, it is rarely a good idea to specialize a function template: overloads, or dispatching to a template class, is usually better.
Note that the language talks about 'more specialized' in overload resolution: do not confuse this with 'template specialization': they are distinct concepts that unfortunetally share a word.
As mentioned in other answers, the reason is that the signature of the
explicit function specialization is not taking part in overload
resolution.
A simple rule of thumb for explicit specializations is that they change the the definition that will be used when it's primary template is called with the specific template arguments.
template <typename T> void foo (T) {
// definition used for 'foo' when T is not 'int'
}
template <> void foo<int> (int) {
// definition used for 'foo' when T is 'int'
}
The compiler performs the following steps when selecting the best swap (I'll ignore exception specifications for brevity):
namespace A
{
template <typename T> struct Foo { };
template <typename T> void swap (Foo<T> &, Foo<T> &);
}
namespace std
{
// swap provided by the STL
template <typename T> void swap (T &, T &);
// explicit specialization of std::swap
template <> void swap (Foo<int> &, Foo<intT> &) { }
}
Specializations of the primary templates are generated for both swaps:
13.3.1p7: In each case where a candidate is a function template,
candidate function template specializations are generated using
template argument deduction (14.8.3, 14.8.2). Those candidates are
then handled as candidate functions in the usual way.
NB: The explicit specialization is not part of this.
For swap(a,b) the candidate set used by overload resolution will
contain the following generated function template specializations:
A::swap(Foo<int>&, Foo<int>)&);
std::swap(Foo<int>&, Foo<int>)&);
Both are generated template specializations and both have exactly the same conversion sequences for the arguments so to determine which template to use the following bullet in the Best Viable Function says:
13.3.3p1b7: F1 and F2 are function template specializations, and the
function template for F1 is more specialized than the template for
F2 according to the partial ordering rules described in 14.5.6.2.
Partial ordering comes down to comparing the function parameter lists to find which is more specialized. In this example, Foo<T> is more specialized than T and so swap(Foo<T>&, Foo<T>&) is considered a better match than swap(T&,T&). The result is that A::swap is selected and so the explicit specialization of std::swap is ignored.
If the code is changed so the explicit specialization is for A::swap rather than std::swap then as A::swap wins overload resolution, then the explicit specialization will be used:
namespace A
{
template <typename T> struct Foo { };
template <typename T> void swap (Foo<T> &, Foo<T> &);
// explicit specialization of A::swap
template <> void swap (Foo<int> &, Foo<intT> &) { }
}
I am looking at some c++ code and do not understand the purpose of the template declaration in this situation:
template<> void operator>>(const ClassA& s, const ClassB d) {...}
What is the semantic of template<>?
This is, indeed, template specialization, as others before mentioned. There must be some previously declared function template, such as:
template<typename T, typename U>
void operator>>(const T& s, const U d) {...}
However, it is quite misguided. It is much better to remove the template<> altogether, so operator>> would just be overloaded. The problem with function template specialization is that it may lead to unexpected behaviour in the presence of overloaded functions (and operator>> has lots of overloads), since the specialization does not overload. This means that the compiler first selects the most appropriate overload for the function and then, if the selected overload is a function template, it looks for template specializations to see if there is an appropriate one.
A classical example (unfortunately, I don't remember where I read it). Consider this overloaded function template:
template <typename T>
void Function(T param);
template <typename T>
void Function(T* param);
template <>
void Function(int* param);
main()
{
int i = 5;
Function(&i);
}
As expected, the template specialization for int* is called. But just change the order of the function definitions:
template <typename T>
void Function(T param);
template <>
void Function(int* param);
template <typename T>
void Function(T* param);
main()
{
int i = 5;
Function(&i);
}
Now the general template for T* is called, since we are specializing the template for T, not for T*, and this second template is better suited for our call. This would be avoided if we overloaded the function instead of specializing the template:
void Function(int* param);
Now the order of declaration does not matter, we will always call the overload for int*.
UPDATE: Now I know who to credit. I read about this in an article by Herb Sutter. The example was provided by Peter Dimov and Dave Abrahams.
This is Template specialization
You use this syntax when you want to provide a special handler for a particular template type. Consider:
// A normal template definition.
template <typename AType>
whoami () { std::cout << "I am an unknown type."; }
// Now we specialize.
template <>
whoami<int> () { std::cout << "I am an integer!"; }
There's some other nonsense involved, particularly "partial specialization", but that's the basic function of template <>.
It is a template specialization: (fully or partially) resolving the template for a specific type. (Your particular example seems to be a full specialization, as no more template parameters are left unresolved in it. If the template has multiple parameters, and you specialize only some of them, it is called partial template specialization)
This allows one to provide type-specific optimizations for a given template, or to do many clever tricks such as detecting the static type of variables etc.
Does C++ standard guarantee the following?:
template<typename T>
void function(T (&)[1]);
template<typename T>
void function(T*);
int a[1];
function(a); // first function gets called, not second version
Yes, this is guaranteed, but the reason is different than what GMan says. The "array of length 1" overload will be selected because it is more specialized than the second in template functions partial order. Basically, it means that an argument in the form T(&)[1] will always match the second template argument in the form T*, so the first overload will always be selected when conversion sequences don't decide.
From 13.3.3:
Given these definitions, a viable
function F1 is defined to be a better
function than another viable function
F2 if for all arguments i, ICSi(F1) is
not a worse conversion sequence than
ICSi(F2), and then
for some argument j, ICSj(F1) is a better conversion sequence than
ICSj(F2), or, if not that,
F1 is a non-template function and F2 is a template function specialization,
or, if not that,
F1 and F2 are template functions, and the function template for F1 is
more specialized than the tem- plate
for F2 according to the partial
ordering rules described in 14.5.5.2,
or, if not that,
...
Normal functions are only affected by the first item; when any template functions are in the set of candidate functions, the second or third item can decide. The reason we want it like that is we want to be able to write seemingly ambiguous templated overloads. Eg.
template <class T> void f(T);
template <class T> void f(T*);
would otherwise be ambiguous for int*. In C++0x, you can even write declarations like:
template <class ...Ts> void f(const Ts&... args);
template <class T, class ... Ts> void f(const T& a, const Ts&... args);
and the second will be selected whenever there is at least one argument.