C++ function resolution matches different function when I adjust their sequence
Asked Answered
L

1

5

I've got a test program to see how compiler(g++) match template function:

#include<stdio.h>
template<class T>void f(T){printf("T\n");}
template<class T>void f(T*){printf("T*\n");}
template<>       void f(int*){printf("int*\n");}
int main(int argc,char**) {
    int *p = &argc;
    f(p); // int*
    return 0;
}

It prints int*. Seems the specialized template is the high priority match? Then I switched the function declaration a bit, this time:

#include<stdio.h>
template<class T>void f(T){printf("T\n");}
template<>       void f(int*){printf("int*\n");}
template<class T>void f(T*){printf("T*\n");}
int main(int argc,char**) {
    int *p = &argc;
    f(p); // T*
    return 0;
}

It prints T*. The only difference between the 2 programs is I changed the function declaration for overloaded "f" a bit, why the result is different?

Lucilius answered 27/6, 2022 at 23:59 Comment(4)
It's more, or less, the same reason why C++ developers, on average, consume much more coffee, or alcohol, or both, than everyone else.Keystroke
To be fair to your compiler, you aren't really giving it clarity as to which specialization it chooses. Seems to me that the last one in the list is probably as good a choice as the first.Lexeme
And for the record, MSVC does the same.Lexeme
FWIW, this is one of the few things that the C++ standards explicitly warns about (and does so in a humorous way): 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. :)Briarwood
G
6

You have two (overloaded) template functions here, and a third function f(int*) that is specializing one of the template functions.

The specialization happens after after the overload resolution. So in both cases you will select f(T*) over f(T). However, in the first case when you have specialized f(T*), you will get the int* specialization. In the second case, when you have specialized f(T), the selected function has no specialization.

Remember that you can't partially-specialize a template function, only fully specialize it. If you want f always to print int*, then consider making f(int*) a regular function, rather than a template specialization.

Gonsalves answered 28/6, 2022 at 0:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.