10

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?

tomwesolowski
  • 956
  • 1
  • 11
  • 27
  • 8
    http://www.gotw.ca/publications/mill17.htm – catscradle Sep 01 '13 at 11:28
  • @catscradle Nice link, but it doesn't explain the effects of changing the definitions order. – LorenzoDonati4Ukraine-OnStrike Sep 01 '13 at 12:02
  • @LorenzoDonati: it does, try and re-read it :) – Matthieu M. Sep 01 '13 at 13:23
  • @MatthieuM. Ok. I reread it and felt dumb for a while :). It is clear that two base template overloads and specializations are ignored until a base is selected. In our situation the base templates are 1 and 3, while 2 is a specialization of ... 2 or 3? My template-fu is failing me now! The only explanation I find is that 2 is seen as a specialization of either 1 or 3 depending on its position relative to 2 and 3. Is my inference right? – LorenzoDonati4Ukraine-OnStrike Sep 01 '13 at 13:49
  • @MatthieuM.The explanation is in Dietmar's answer (I commented before I read it - sorry for the noise). Still I couldn't find the place *in the doc linked by catscradle* where it explains (or hints at) this order dependency. I'd really appreciate a more precise pointer. – LorenzoDonati4Ukraine-OnStrike Sep 01 '13 at 14:22
  • @LorenzoDonati: hopefully, Dietmar's answer is now such a pointer (and don't feel dumb, the gotw site has stuff of varying levels and this one is really arcane...) – Matthieu M. Sep 01 '13 at 14:37
  • (just adding some feedback) That's why I generally don't specialize function templates and when I do, I _always specify the explicit type(s) in the angle brackets_. For your current code, #2 is actually `c(int*)` (explicit specialization of overload `c(T)` for `T`=`int*`), and when you move it after #3 it is then `c(int*)` (explicit specialization of overload `c(T*)` for `T`=`int`). Writing it _explicitly_ enables to choose ( http://ideone.com/U8T7YF or http://ideone.com/hUGiOI ) or to prevent unwanted code from compiling ( http://ideone.com/97uw9A vs http://ideone.com/0OMD2Y ). – gx_ Sep 03 '13 at 17:47

1 Answers1

14

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
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • This quote has got to be an elaborate joke. – jrok Sep 01 '13 at 12:29
  • 4
    @jrok: Of course, it is primarily a joke! This limerick was sneaked into normative text of the standard in Morristown, i.e., at the meeting where the FDIS for C++98 was voted out. The person responsible for the template section had stated that no jokes will be allowed, i.e., it took some engineering to make it happen (just read the rest of this paragraph to see what was done to hide it). – Dietmar Kühl Sep 01 '13 at 12:33
  • @DietmarKühl: best Standard quote ever! – Matthieu M. Sep 01 '13 at 13:28
  • @MatthieuM. It is even a [limerick](http://www.gregcons.com/KateBlog/LimerickInTheCStandard.aspx) – TemplateRex Sep 01 '13 at 14:17
  • @DietmarKühl Aha, so repeating the word `template` 21 time wasn't a technical neccesity? :) – jrok Sep 01 '13 at 14:53
  • @DietmarKühl it is refreshing to discover that there are people with the sense of humor in standardization boards :) – LorenzoDonati4Ukraine-OnStrike Sep 01 '13 at 15:16