views:

104

answers:

1

I have the following set of templates:

//1  
template< typename T > void funcT( T arg )  
{
    std::cout<<"1: template< typename T > void funcT( T arg )";  
}  
//2  
template< typename T > void funcT( T * arg )  
{
    std::cout<<"2: template< typename T > void funcT( T * arg )";  
}  
//3  
template<> void funcT< int >( int arg )  
{  
    std::cout<<"3: template<> void funcT< int >( int arg )";  
}  
//4  
template<> void funcT< int * >( int * arg )  
{  
    std::cout<<"4: template<> void funcT< int *>( int * arg )";  
}  

//...  

int x1 = 10;  
funcT( x1 );  
funcT( &x1 );  

Can someone please explain why funcT( x1 ); calls function #3 and funcT( &x1 ); calls function #2 but not #4 as expected?
I have already read this article http://www.gotw.ca/publications/mill17.htm which says that "overload resolution ignores specializations and operates on the base function templates only". But according to this logic funcT( x1 ); should call function #1, not #3. I am confused.

+9  A: 

Functions #3 and #4 are specializations of #1, not of #1 and #2 respectively.

This means that your compiler will choose between #1 and #2 first. When it has selected #1 to be the best fit for funcT(x1), it then selects the specialization, #3. For funcT(&x1), it chooses #2 as the best fit and finds no specializations.

By writing #4 as

template<> void funcT<>( int * arg )

it becomes a specialization of #2 and you'll get the expected result that #4 is called for funcT(&x1).

Another option would be to simply write

void funcT(int *arg)

since regular functions will always be chosen instead of templated versions if they match.

villintehaspam
Right. You could add that, to make #4 a specialization of #2 and get the "expected" behavior, it should be written as `template<> void funcT<>(int* arg)`
Éric Malenfant
@Éric Malenfant: correct, I'm not sure whether your comment or my edit came first, but thanks anyway.
villintehaspam
Why is it `template<> void funcT<>( int * arg )` and not `template<> void funcT<int>( int * arg )`?
sepp2k
@sepp2k: I'd say that <int> would work as well. The OP uses <int*> however, which tells the compiler that T=int*, so that would mean that #2 has the parameter T* = int**, so it's not a match.
villintehaspam