6

考虑这个函数模板:

template<typename T>
unsigned long f(void *) { return 0;}

f<A>现在,我将和的地址打印f<B>为:

std::cout << (void*)f<A> << std::endl;
std::cout << (void*)f<B> << std::endl;

如果在 MSVS10 中编译,为什么它们会打印相同的地址?它们不是两个不同的功能,因此应该打印不同的地址吗?

更新:

我意识到在ideone上,它会打印不同的地址。MSVS10 优化了代码,因为函数不依赖T于任何方式,所以它产生相同的函数。@Mark 对此的回答和评论很有价值。:-)

4

3 回答 3

7

您需要转换为void *

std::cout << (void*)(ftype*)f<A> << std::endl;
std::cout << (void*)(ftype*)f<B> << std::endl;

如果您强制转换为函数指针(或其他几个非空指针类),它将被 for 解释为 a booloperator<<因此std::ostream1)。

于 2012-02-17T05:19:35.100 回答
2

由于该函数不依赖于模板参数,因此编译器可以将所有实例化压缩为一个函数。

我不知道你为什么要1地址。


纳瓦兹添加:

我用我的真实代码进行了试验,并得出结论@Mark上面所说的在这里非常重要:

由于该函数不依赖于模板参数,因此编译器可以将所有实例化压缩为一个函数。

我还得出一个结论,如果函数体依赖于T*,而不是依赖于T,它仍然会在我的真实代码中为不同类型的参数生成相同的函数(但不是在 ideone 上)。但是,如果它依赖于T,那么它会产生不同的函数,因为sizeof(T)不同类型的参数不同(幸运的是我)。

所以我在函数模板中添加了一个虚拟类型的自动变量 T,这样函数就可以依赖于它的大小,T从而强制它产生不同的函数。

于 2012-02-17T05:20:32.227 回答
1

这只是一种未定义行为的情况,因为将指向函数的指针转换为指向对象类型的指针的结果是未定义的。

要检查的更有趣的表达式是f<A> == f<B>which 应该评估为true当且仅当A并且B引用相同的类型。

于 2012-02-17T06:57:27.777 回答