如何确定夹心模板将被使用

时间:2019-06-06 08:25:31

标签: c++ templates

我正在学习c ++中的模板,并且找到了以下示例。

据我了解,如果没有匹配的非模板函数,则编译器应始终尝试使用最“专业化”的模板,但是在此示例中,第一次调用导致调用函数a(T *)而不是a(int *)。为什么?为什么第二通电话的行为有所不同?

template<typename T>
void a(T) {cout << "(T)" << endl;}

template<>
void a<>(int*) {cout << "(int)" << endl;}

template<typename T>
void a(T*) {cout << "(T*)" << endl;}

template<typename T>
void b(T) {cout << "(T)" << endl;}

template<typename T>
void b(T*) {cout << "(T*)" << endl;}

template<>
void b<>(int*) {cout << "(int)" << endl;}

int main()
{
  int i;
  a(&i);
  b(&i); 
  return 0;
}

结果输出为:

(T*)
(int)

我希望它是:

(int)
(int)

2 个答案:

答案 0 :(得分:6)

仅考虑主模板(因此无需专门化)来选择更多专门化的重载。

一旦选择了主模板,我们就会使用专业化。

现在,template<> void a<>(int*);只能是template<typename T> void a(T)的专业化版本(尚未看到其他版本)。

template<> void b<>(int*);template<typename T> void b(T*)的专业化(这是更专业的匹配重载)。

请注意,您可以通过提供模板而不是让编译器推论来选择b的特化:

  • template<> void b<>(int*)-> template<typename T> void b(T*) with T=int
  • template<> void b<int>(int*)-> template<typename T> void b(T*) with T=int
  • template<> void b<int*>(int*)-> template<typename T> void b(T) with T=int*

如此:

int i;
a(&i); // a<T*> with T=int*, no specialization for a<U*> (U=int) exist -> generic template called
b(&i); // b<T*> with T=int*, specialization for b<U*> (U=int) exists -> specialization called

答案 1 :(得分:2)

由于声明顺序的不同,专业化属于不同的主模板。

对于第一种情况,专业化属于a(T)。对于第二种情况,专业化属于b(T*)。在主模板之间的重载解析期间,始终选择采用T*的版本;那么在第一种情况下,将不会考虑专业化,因为它不是a(T*的专业化。但这是在第二种情况下选择的,因为b(T*)具有专业性。

第一种情况

超载

  • a(T)
    • 专业化-> a(int *)
  • a(T *)//以过载分辨率选择

第二种情况

超载

  • b(T)
  • b(T *)//以重载分辨率选择
    • 专业化-> b(int *)//然后选择专业化