c++ - 重载解析在模板函数中的工作方式是否不同?
问题描述
考虑这段代码。
在进一步阅读之前尝试猜测程序的输出:
#include <iostream>
using namespace std;
template <typename T>
void adl(T) {
cout << "T";
}
struct S {
};
template <typename T>
void call_adl(T t) {
adl(S());
adl(t);
}
void adl(S) {
cout << "S";
}
int main() {
call_adl(S());
}
你好了吗?好的。
所以这个程序的输出是TS
,这看起来违反直觉(至少对我来说)。
为什么adl(S())
内部调用call_adl
使用模板重载而不是使用 S 的调用?
解决方案
对于模板中的依赖名称和非依赖名称,名称查找的行为是不同的。
对于模板定义中使用的非依赖名称,在检查模板定义时会进行非限定名称查找。在该点对声明的绑定不受实例化点可见的声明的影响。对于模板定义中使用的依赖名称,查找被推迟到模板参数已知,此时 ADL 检查
with external linkage (until C++11)
从模板定义上下文以及模板实例化上下文中可见的函数声明,而非 ADL 查找仅检查with external linkage (until C++11)
从模板定义上下文可见的函数声明(换句话说,在模板定义之后添加新函数声明不会使其可见,除非通过 ADL)。
这意味着 for adl(S());
,adl(S)
声明后call_adl
不可见,然后adl(T)
选择模板。对于adl(t);
,t
是一个依赖名称(取决于模板参数T
),查找被推迟并由 ADL 找到,并在重载决议中adl(S)
胜出。adl(T)
推荐阅读
- vba - 第一行数据未显示正确数据
- regex - 用于特定测试的 Mocha Grep Regex
- php - 在php中打印正确的日期
- python - Python 请求:如何确定 MaxRetries 异常的响应代码
- powerbi - 需要 PowerBI Datediff 协助
- rest - GrailsView 解析 jsonApi 发布数据 - Grails 团队是否在 jsonViews 中做通用解决方案?
- html - 链接到外部 url 的角度重定向到应用程序
- javascript - 在 Chrome 中查找并复制 onclick 行为?
- python - 如何通过代理自动连接到 Cloud SQL?
- angular - 引导工具提示标题属性不适用于 Angular 6