Шаблоны С++ - специализированные функции

У меня есть следующий код:

//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);

Может кто-нибудь объяснить мне, почему в следующем примере компилятор выбирает функцию # 3, но когда я меняю порядок функций # 2 и # 3, компилятор выбирает функцию # 2?

Ответ 1

Сначала компилятор выбирает первичный шаблон и только затем определяет, какую специализацию использовать. То есть в вашем случае компилятор всегда выбирает второй первичный шаблон, т.е. # 3.

Однако, поскольку вы не указали аргумент шаблона при специализировании шаблона функции, ваша специализация специализируется на различном основном шаблоне в зависимости от его местоположения: с заданным порядком он специализируется на первом основном шаблоне, когда вы обмениваете порядок # 2 и # 3 он специализируется на втором основном шаблоне. В пункте 14.7.3 [temp.expl.spec] стандарт должен сказать следующее о ситуации

... При написании специализации будьте осторожны с ее местоположением; или сделать его компиляцией, станет таким испытанием, чтобы разжечь его самосожжение.

Если вы хотите контролировать, какой первичный шаблон специализация действительно специализируется, вы должны указать аргументы шаблона в специализации:

template <> void c<int*>(int* in) { ... } // specializes the first primary
template <> void c<int>(int* in)  { ... } // specializes the second primary