我(可能)有一个简单的问题。 什么时候必须声明模板中使用的函数? 打印出以下代码(使用 gcc >=4.1):
init my A object
no init
使用 gcc 4.0 打印出以下代码:
init my A object
init my string object
#include <iostream>
#include <string>
template<typename T>
void init(T& t){
std::cout << "no init" << std::endl;
}
// void init(std::string& t);
template <typename T>
void doSomething(T& t){
init(t);
// do some further stuff
}
void init(std::string& t){
std::cout << "init my string object" << std::endl;
}
class A{
};
void init(A& t){
std::cout << "init my A object" << std::endl;
}
int main(){
A a;
doSomething(a);
std::string s("test");
doSomething(s);
return 0;
}
std::string 和 A 的用法有什么区别? 难道不应该有同样的行为吗?
通过附加的前向声明,它可以正常工作, 但我什么时候需要它?
干杯, CSpille
最佳答案
仅使用参数相关查找(在与函数参数关联的命名空间中查找函数)来查找实例化点处的函数。正常查找仅在模板定义处完成。
因此,对于 std::string
来说,只有通用的 init
函数模板可见并被调用,因为命名空间 std< 中没有特定的函数模板。/
。对于A
,更具体的函数可以在A
的全局命名空间中找到。
如果您向前声明字符串特定函数出现在 doSomething
之前,则正常的非限定查找会在定义处找到它并稍后使用它。
如果您按如下方式调用 init
,它将禁止参数相关查找,因此也会使用 A
的通用模板。
template <typename T>
void doSomething(T& t){
(init)(t);
// won't do ADL
}
(作为旁节点:在这种情况下,不仅在实例化时禁止参数依赖查找,而且 init
首先不会是依赖名称 - 仅是非括号和不合格的函数名称是相关的。因此,无论如何,仅在定义时进行非 ADL 查找,并且在实例化时不会进行任何查找,即使存在与在那里进行的 ADL 不同的形式。)
关于c++ - 什么时候必须声明模板中使用的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3178478/