Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Templates - specializing functions

I have the following code:

//1
template<typename T>
void c(T in) {
    cout << "Template c(" << in << ")" << endl;
}
//2
template<>
void c<>(int* in) { 
        cout << "Template specialization b(" << in << ")" <<endl;
}
//3
template<typename T>
void c(T* in) {
        cout << "Template for pointers c(" << in << ")" <<endl;
}
//..
int i = 8;
c(&i);

Can someone explain me why in the following example compiler choose function #3, but when I change the order of functions #2 and #3, then compiler choose function #2?

like image 427
tomwesolowski Avatar asked Sep 01 '13 11:09

tomwesolowski


People also ask

What is function template specialization?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.

Can you partially specialize a C++ function template?

You can choose to specialize only some of the parameters of a class template. This is known as partial specialization. Note that function templates cannot be partially specialized; use overloading to achieve the same effect.

What is the difference between template and function?

A function definition can only be provided once in a given program (unless the function is marked inline ). A function template can be defined in multiple translation units, and the linker will pick one copy of each actual instantiation.

What is the main advantage of using template functions in C++?

Advantages of Using Templates in C++ Templates are type-safe. They are generally considered as an improvement over macros for these purposes. Templates avoid some common errors found in code that make heavy use of function-like macros. Both templates and macros are expanded at compile time.


1 Answers

The compiler first chooses the primary template and only then determines which specialization to use. That is, in your case the compiler always chooses the second primary template, i.e., #3.

However, since you didn't specify the template argument when specializing the function template, your specialization specializes a different primary template depending on its location: with the given order, it specializes the first primary template, when you exchange the order of #2 and #3 it specializes the the second primary template. In 14.7.3 [temp.expl.spec] paragraph 7 the standard has to say the following about the situation

... When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.

If you wanted to control which primary template the specialization actually specializes, you would specify the template arguments in the specialization:

template <> void c<int*>(int* in) { ... } // specializes the first primary
template <> void c<int>(int* in)  { ... } // specializes the second primary
like image 116
Dietmar Kühl Avatar answered Oct 21 '22 13:10

Dietmar Kühl