我正在阅读有关模板函数的内容,并对这个问题感到困惑:
#include <iostream>
void f(int) {
std::cout << "f(int)\n";
}
template<typename T>
void g(T val) {
std::cout << typeid(val).name() << " ";
f(val);
}
void f(double) {
std::cout << "f(double)\n";
}
template void g<double>(double);
int main() {
f(1.0); // f(double)
f(1); // f(int)
g(1.0); // d f(int), this is surprising
g(1); // i f(int)
}
如果我不写template void g<double>(double);
,结果是一样的.
我认为g<double>
应该在 f(double)
之后实例化,因此调用 f
在g
应该打电话f(double)
。令人惊讶的是,它仍然调用 f(int)
在g<double>
。谁能帮我理解这个?
读完答案后,我明白了我的困惑到底是什么。
这是一个更新的示例。除了我添加了 g<double>
的特化之外,它基本上没有变化。 :
#include <iostream>
void f(int){cout << "f(int)" << endl;}
template<typename T>
void g(T val)
{
cout << typeid(val).name() << " ";
f(val);
}
void f(double){cout << "f(double)" << endl;}
//Now use user specialization to replace
//template void g<double>(double);
template<>
void g<double>(double val)
{
cout << typeid(val).name() << " ";
f(val);
}
int main() {
f(1.0); // f(double)
f(1); // f(int)
g(1.0); // now d f(double)
g(1); // i f(int)
}
随着用户特化,g(1.0)
表现如我所料。
编译器是否应该自动对 g<double>
进行相同的实例化?在同一个地方(或者甚至在 main()
之后,如 The C++ Programming Language 第 26.3.3 节所述,第四版)?
最佳答案
名称f
是一个从属名称(它通过参数val
依赖于T
),它将被解析为two steps :
- Non-ADL lookup examines function declarations ... that are visible from the template definition context.
- ADL examines function declarations ... that are visible from either the template definition context or the template instantiation context.
void f(double)
从模板定义上下文中不可见,ADL 也找不到它,because
<小时/>For arguments of fundamental type, the associated set of namespaces and classes is empty
我们可以稍微修改您的示例:
struct Int {};
struct Double : Int {};
void f(Int) {
std::cout << "f(Int)";
}
template<typename T>
void g(T val) {
std::cout << typeid(val).name() << ' ';
f(val);
// (f)(val);
}
void f(Double) {
std::cout << "f(Double)";
}
int main() {
g(Double{});
}
现在 ADL 将在第二步中找到 void f(Double)
,输出将为 6Double f(Double)
。我们可以通过编写 (f)(val)
(或 ::f(val)
)而不是 f(val)
来禁用 ADL。那么输出将为 6Double f(Int)
,与您的示例一致。
关于c++ - 为什么这个模板函数没有按预期运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59099466/