模板推演和重载
Template deduction and overloading
这是入门 c++ 5th 中的一个练习:
template <typename T> void f(T); //1
template <typename T> void f(const T*); //2
template <typename T> void g(T); //3
template <typename T> void g(T*); //4
int i = 42, *p = &i;
const int ci = 0, *p2 = &ci;
g(42); g(p); g(ci); g(p2);
f(42); f(p); f(ci); f(p2);
答案是:
g(42); //type: int(rvalue) call template 3 T: int instantiation: void g(int)
g(p); //type: int * call template 4 T: int instantiation: void g(int *)
g(ci); //type: const int call template 3 T: const int instantiation: void g(const int)
g(p2); //type: const int * call template 4 T: const int instantiation: void g(const int *)
f(42); //type: int(rvalue) call template 1 T: int instantiation: void f(int)
f(p); //type: int * call template 1 T: int * instantiation: void f(int *)
f(ci); //type: const int call template 1 T: const int instantiation: void f(const int)
f(p2); //type: const int * call template 2 T:int instantiation: void f(const int *)
我的问题是为什么f(p)
赞成f(T)
的实例化而不是f(const T *)
简而言之,在重载解析中包含函数模板的规则是:
-
名称查找确定一组可见的函数、对象和函数模板。
-
集合中的每个函数模板从任何显式参数、推导和/或默认模板参数中确定其模板参数,如果可能,这些参数将被替换以获得一个特定的具体函数签名。 (如果不可能,则只是将函数模板从集合中抛出。 当模板参数推断失败以及将参数替换到签名中失败(也称为"SFINAE"规则)时,可能会发生这种情况。
-
这些函数使用正常的重载解析规则进行比较,将来自模板的签名完全视为普通的非模板函数。
-
仅当步骤 3 认为其中两个函数不明确时,这些决胜规则才适用:
一个。如果一个函数签名来自模板,而另一个不是,则认为非模板函数更好。
二.如果两个函数签名都来自模板,并且一个模板比另一个模板"更专业",则认为更专业的模板更好。 (简而言之,"更专业"本质上意味着我们可以证明对更专业的模板的任何有效参数也是对不太专业的模板的有效参数,但反之则不然。
在本示例的f(p)
表达式中,在步骤 2 中,模板 #1 推导T=int*
,模板 #2 推导T=int
,因此签名为:
void f(int*); // from 1
void f(const int*); // from 2
在步骤 3 中,参数p
的类型为int*
,因此 #1 中的void f(int*);
使用标识转换(完全匹配),#2 中的void f(const int*);
使用指针转换,因此 #1 中的void f(int*);
获胜,并且该函数模板专用化是命名的函数模板专用化。
确实,模板 #2void f(const T*);
比模板 #1void f(T);
更专业。 但是由于第 3 步决定了答案,我们永远不会进入第 4 步,所以这在这里并不重要。 (步骤 4 确实适用于另一个表达式f(p2)
。
这不是语言律师的答案,但基本上:
f(T)
与T=int*
完全匹配int*
f(T const*)
与T=int
并不完全匹配int*
。
完全匹配获胜。
- 继承函数的重载解析
- 你能重载对象变量名本身返回的内容吗
- 从父命名空间重载类型
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 重载操作程序时出错>>用于类中的字符串 memebr
- 一个关于在C++中重载布尔运算符的问题
- 不同翻译单元中不可重载的非内联函数定义
- 为什么使用SFINAE而不是函数重载
- 为什么我不能在 C++ 中的特定函数重载中调用同一函数的任何其他重载?
- 将重载的成员函数传递给函数模板
- c++:可变模板和函数重载
- 重载元组索引运算符-C++
- 如何使用重载的相等(==)运算符向测试用例添加描述
- 重载==不适用于二进制树
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 重载运算符new[]的行为取决于析构函数
- 正在尝试重载二进制搜索树分配运算符
- 重载Singly Linked List中的赋值运算符
- 取消引用运算符不能重载