tags:

views:

140

answers:

2
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?

+2  A: 

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.

sbi
In my initial read of the code, I see no difference in the signatures between the overload and the specialization, other than the template. Why, then, would `max(1,'2')` not be matched by the specialization? More specifically, why is `1`, an `int`, converted to `char` in the overload case but not in the specialization case?
rcollyer
@rcollyer: See the Quote *#66* in Gregorys answer.
Georg Fritzsche
@rcollyer: The simple answer is: _Because the standard says so._ `template<> void max(...)` is the syntax for a template __specialization__; `void max(...)` is the syntax for a function __overload__. The rules for matching overloaded functions are different from the rules for matching template specializations. (And overloads are chosen _first_ and only if a template is chosen, are possible specializations considered.) Why choosing overloads is so much more relaxed than choosing specializations, I can't say. But I guess that, would rules for overloads be made up _now_, they'd be stricter, too.
sbi
@sbi: ah, I see it now. Thanks.
rcollyer
Ouch, that formatting is broken. Too bad I hadn't seen it.
sbi
+7  A: 
  1. is a template function
  2. is a total specialization of the previous template function (doesn't overload!)
  3. 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:

Gregory Pakosz
i just fixed the typos in the code, sorry for that
Gregory Pakosz
added gotw links, same as those given by @Michael
Gregory Pakosz
thanx i understood the point :)
Ah, I was just about to add the "implementing the function template in terms of a class template"-trick to my answer, but yours is much better anyway. +1 from me.
sbi