【问题标题】:C++ different template methods called on same variableC ++在同一个变量上调用不同的模板方法
【发布时间】:2014-08-06 08:09:06
【问题描述】:

有人能解释一下为什么一次使用方法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*)

【问题讨论】:

标签: c++ templates template-specialization


【解决方案1】:
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

【讨论】:

  • 这是一种非常简洁的信息呈现方式,很好:)
  • @MatthieuM。谢谢。
【解决方案2】:

重载解析只选择一个基本模板(或一个非模板函数,如果有的话)。只有在决定选择哪个基本模板并且该选择被锁定后,编译器才会环顾四周,看看是否恰好有该模板的合适特化可用,如果有,那么该特化将被使用。

对于函数c,特化void c&lt;&gt;(int*) 用于void c(T) 重载,而对于d,特化void d&lt;&gt;(int*) 用于void d(T*) 重载。

因此,根据上述解释,首先检查void c(T),并忽略打印出的更好的重载void c(T*)(没有专门化)。对于dvoid d(T*) 重载也被锁定,但随后特化 void d(int*) 被记录并被选中。

【讨论】:

    【解决方案3】:

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

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

    对于函数模板,它们分为两组:

    • “基础”函数模板
    • 专用函数模板

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

    1. 在常规函数和“基本”函数模板中选择最佳匹配
    2. 如果在步骤 1 中选择了“base”函数模板,则选择最佳专业化(如果有匹配,否则使用“base”)

    在你的两个例子中,最好的“基本”函数是c(T*)d(T*),所以这是不同的第二步。为什么?

    因为,作为函数模板的特化,函数模板必须先声明

    因此:

    • c&lt;&gt;(int*)c(T) 的专业化
    • d&lt;&gt;(int*)d(T*) 的特化

    因此,当c(T*)在步骤1中挑选时,当d(T*) 987654328 d&lt;&gt;(int*)是一个更好的专业化时,没有更好的专业化。

    因为这很棘手,专家的建议……是不要使用函数模板专业化。它只是奇怪地与函数模板重载混合在一起。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-04
      • 1970-01-01
      • 2018-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多