anurag86
anurag86

Reputation: 1687

"specializations don’t participate in overloading"

What does it really mean by "Specialization of function templates Don't take part in overload resolution. Only base templates are considered"

I wrote a simple template function with its specialized verion and could see that specialized was called:

// Base template
template <typename T>
T max(T a, T b) {
    std::cout << "Base Template" << std::endl;
    return (a>b) ? a : b;
}

// Specialization for int
template<>
int max<int>(int a, int b) {
    std::cout << "int specialization" << std::endl;
    return (a>b) ? a : b;
}
max(2,3);// prints "int specialization"

Looking at other StackOverflow related to this concept, i found another post in which to prove that specializations don't take part in overloading he showed the following example in which the specialized version was not called and i am still not sure why it was not called. But apart from that, in this example, the argument doesn't have a variable name still there is no compile or runtime error for the part (char const* const&)

template<typename T>
void f(T const&)
{
        std::cout<<std::endl<<"Base Template for f() called\n";
}

template<>
void f<char const * const &>(char const* const&)
{
        std::cout<<std::endl<<"Specialized f() for char const* called\n";
}
f("Hello") //prints "Base Template for f() called"

In all, i am still trying to figure out the meaning of "Specialization of function templates Don't take part in overload resolution. Only base templates are considered", if someone could explain with an example(and why Base Template was called in second example). And secondly, why the program compiled and ran fine without variable name in second example.

Upvotes: 5

Views: 455

Answers (1)

Sneaky Turtle
Sneaky Turtle

Reputation: 301

If you try max(5, 7.0), you'll get an error even though a double is convertible to an int. So the int specialisation of max doesn't participate in overload resolution.

template <typename T>
T max(T a, T b);

template <>
int max(int a, int b);

max(5, 7.0); // compiler error (no matching function)

However, if you had used a regular function instead of a template specialisation, you'd get the expected behaviour.

template <typename T>
T max(T a, T b);

int max(int a, int b);

max(5, 7.0); // this is fine

When the compiler considers the argument types (int, double), it looks for functions in the following order (it's a little more complicated than this with ADL and other details):

  • exactly matching functions (e.g. max(int, double). So max(int, int) won't be considered at this stage)
  • matching function templates (e.g. max(T, U). So max(T, T) won't be considered because T can't be both int and double)
  • functions with compatible arguments (e.g. max(int, int) since double is implicitly convertible to int)

Notice that I didn't mention function template specialisations. If a matching function template is found, an exactly matching specialisation will be used (so if you specialised for doubles but you call with ints that specialisation won't be used), otherwise the base template will be used.

For a better explanation, see cppreference.

Upvotes: 6

Related Questions