Question

I'm really confused by certain details of template overloading/specialization resolution rules. I tried to get some understanding on the subject by going through this article by Herb Sutter on template overloading/specialization. I'm stuck on the following specific point in the article.

Here it is

Consider the following code:
// Example 2: Explicit specialization 
// 
template<class T> // (a) a base template 
void f( T );
template<class T> // (b) a second base template, overloads (a) 
void f( T* );     //     (function templates can't be partially 
                  //     specialized; they overload instead)
template<>        // (c) explicit specialization of (b) 
void f<>(int*);
// ...
int *p; 
f( p );           // calls (c)
The result for the last line in Example 2 is just what you'd expect. The question of the day, however, is why you expected it. If you expected it for the wrong reason, you will be very surprised by what comes next. After all, "So what," someone might say, "I wrote a specialization for a pointer to int, so obviously that's what should be called" - and that's exactly the wrong reason.
Consider now the following code, put in this form by Peter Dimov and Dave Abrahams:
// Example 3: The Dimov/Abrahams Example 
// 
template<class T> // (a) same old base template as before 
void f( T );
template<>        // (c) explicit specialization, this time of (a)
void f<>(int*);
template<class T> // (b) a second base template, overloads (a) 
void f( T* );
// ...
int *p; 
f( p );           // calls (b)! overload resolution ignores 
                  // specializations and operates on the base 
                  // function templates only

The only difference I see between Example 2 and Example 3 is the order in which the templates b and c are declared. I don't understand why that makes all the difference. What's order of declaration got to do with anything? I must have missed a basic concept of c++, and I don't see an explanation for that in the article.

I'd really appreciate somebody clearing this up for me.

Thanks.

Was it helpful?

Solution

What's order of declaration got to do with anything?

The declaration of a specialization must always follow the declaration of the template which is being specialized (14.7.3/3). In Example 2, (c) is an explicit specialization of both (a) and (b). In Example 3, (c) is only an explicit specialization of (a), since (b) follows it.

When overload resolution is being performed, it doesn't matter whether a template has explicit specializations or not. In both examples, overload resolution selects the template (b) over (a) because it's more specialized (14.5.6.2). In Example 2 it doesn't actually matter which one is selected, because (c) is a specialization of both templates, so it gets called no matter what. In Example 3, it does matter. Because (b) wins overload resolution and (c) is not a specialization of (b), it follows that (c) doesn't get called.

OTHER TIPS

In the second example the specialization happens for the class T template, because the class T* template wasn't even declared yet at the point where the specialization is declared.

So when the compiler goes and looks for the best matching template, it chooses correctly class T* template, which has no specialization.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top