考虑这个功能模板:
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的回答和对此的评论很有价值。 : - )
答案 0 :(得分:7)
你需要施展到void *
:
std::cout << (void*)(ftype*)f<A> << std::endl;
std::cout << (void*)(ftype*)f<B> << std::endl;
如果转换为函数指针(或其他几类非void指针),bool
operator<<
将std::ostream
解释为1
({{1}} {1}})。
答案 1 :(得分:2)
由于函数不依赖于模板参数,编译器可以将所有实例化压缩为单个函数。
我不知道为什么你会得到1
地址。
我尝试了我的真实代码,并得出结论,@Mark上面说的内容非常重要:
由于该函数不依赖于模板参数,因此编译器可以将所有实例化压缩为单个函数。
我还得出结论,如果函数体依赖于T*
而不是T
,它仍然会为我的实际代码中的不同类型参数生成相同的函数(不在ideone上,虽然)。但是,如果它依赖于T
,那么它会生成不同的函数,因为sizeof(T)
对于不同的类型参数有所不同(幸运的是我)。
所以我在函数模板中添加了一个类型为T
的虚拟自动变量,因此该函数可能取决于T
的大小,以便强制它产生不同的功能。
答案 2 :(得分:1)
这只是未定义行为的一种情况,因为将指向函数的指针转换为指向对象类型的指针的结果是未定义的。
要检查的更有趣的表达式是f<A> == f<B>
,当且仅当true
和A
引用相同的类型时才应评估为B
。