C ++不同的模板方法调用同一个变量

时间:2014-06-16 13:19:58

标签: c++ templates template-specialization

有人可以解释为什么曾经使用方法c(T*)和下次d<>(int*)?方法cd似乎与我相同,我无法弄清楚为什么不是同一类型的方法。

#include <iostream>
using namespace std;

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

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

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

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

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

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

int main(){
    int i;
    c(&i);
    d(&i);
    return 0;
}

输出:

(T*)
(int*)

3 个答案:

答案 0 :(得分:18)

你只是偶然发现了一个丑陋的C ++部分。

编译期间的重载决策过程是关于为当前代码找到最佳重载。它是在查找阶段选择的一组函数和函数模板上执行的,旨在识别一个(且只有一个)比其他更好的重载。

对于功能模板,它们分为两组:

  • &#34;基础&#34;功能模板
  • 专业功能模板

并且重载解析过程有两个步骤:

  1. 选择常规功能和&#34; base&#34;之间的最佳匹配。功能模板
  2. 如果&#34; base&#34;功能模板由步骤1选择,选择最佳专业(如果有任何匹配,否则使用&#34; base&#34;)
  3. 在你的两个例子中,最好的&#34;基础&#34;函数是c(T*)d(T*),所以这是不同的第二步。为什么?

    因为要成为函数模板的特化,所以必须首先声明所述函数模板

    因此:

    • c<>(int*)c(T)
    • 的特化
    • d<>(int*)d(T*)
    • 的特化

    因此,当在步骤1中选择c(T*)时,在选择d(T*)时没有更好的专业化,d<>(int*)是更好的专业化。

    因为这很棘手,专家的推荐......不是使用功能模板专业化。它只是奇怪地与函数模板重载混合。

答案 1 :(得分:15)

template <typename T>
void c(T);      // 1: function template

template <>
void c<>(int*); // 2: specialization of 1

template<typename T>
void c(T*);     // 3: overload of 1

template<typename T>
void d(T);      // 4: function template

template<typename T>
void d(T*);     // 5: overload of 4

template<>
void d<>(int*); // 6: specialization of 5

// ...

int i;

c(&i);          // 3 is more appropriate overload than 1

d(&i);          // 5 is more appropriate overload than 4
                // and it has the suitable specialization 6

图:

                    c        d
                   / \      / \
overloads         1  (3)   4  (5)   |
                  |            |    |  priority
specializations   2           (6)   V

答案 2 :(得分:2)

重载分辨率仅选择基本模板(或非模板函数,如果有的话)。只有在确定要选择哪个基本模板并且锁定了该选择之后,编译器才会查看是否有适当的特殊化模板可用,如果是,那么专业化将被使用。

对于函数c,专门化void c<>(int*)用于void c(T)重载,而d专门化void d<>(int*)用于void d(T*)重载。

因此,通过上面的解释,第一个void c(T)被检查,并被忽略了更好的重载void c(T*)(没有特化)被打印出来。对于dvoid d(T*)重载也被锁定,但随后会注明专业化void d(int*),然后选择。