【发布时间】:2020-03-24 17:41:24
【问题描述】:
我正在阅读有关模板函数的内容,但被这个问题弄糊涂了:
#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) 之后实例化,因此在g 中对f 的调用应该调用f(double)。令人惊讶的是,它仍然在g<double> 中调用f(int)。谁能帮我理解这个?
阅读完答案后,我明白了我的困惑到底是什么。
这是一个更新的示例。除了我为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 第 4 版第 26.3.3 节所述) ?
【问题讨论】:
-
最后一个电话,
g(1),给我i f(int)。你写了d f(double)。这是一个错字吗? -
是的。对不起。更新
-
模板的基本原理是支持对用户类型的操作,同时仍然防止用户声明的符号劫持内部库调用。这是一个不可能的妥协,因为模板没有“概念”合同,现在引入这样的合理“合同”为时已晚。
标签: c++ function-templates name-lookup dependent-name unqualified-name