我正在玩一些静态多态性,我正在调用一个函数,该函数在内部根据初始参数的类型调用“正确的”专用函数(基本上我正在做标记)。这是代码:
#include <iostream>
using namespace std;
// tags
struct tag1{};
struct tag2{};
// the compliant types, all should typedef tag_type
struct my_type1
{
using tag_type = tag1;
};
struct my_type2
{
using tag_type = tag2;
};
// static dispatch via tagging
template <typename T>
void f(T)
{
cout << "In void f<typename T>(T)" << endl;
// why can I call f_helper without forward definition?!?
f_helper(typename T::tag_type{});
}
int main()
{
my_type1 type1;
my_type2 type2;
// how does f below knows about f_helper ?!?!
// even after instantiation f_helper shouldn't be visible!
f(type1);
f(type2);
}
// helper functions
void f_helper(tag1)
{
cout << "f called with my_type1" << endl;
}
void f_helper(tag2)
{
cout << "f called with my_type2" << endl;
}
因此,f(T)
使用参数调用my_type1
或my_type2
在内部必须tag_type
使用适当的标签tag1
/进行 typedef 调用tag2
。根据这个 internal tag_type
,然后调用“正确的”包装器,这个决定当然是在编译时做出的。现在我真的不明白为什么这段代码有效?为什么我们不需要前向声明f_helper
?我首先在之前main
(和之后f
)定义了包装器,虽然我还可以,这是有道理的,你不需要转发声明,因为编译器仅在f(type1);
调用(in main()
)时才实例化模板,然后它不知道类型T
,所以在实例化的时候编译器就知道了f_wrapper
。
但是如您所见,即使我声明了包装器 AFTER main()
,代码仍然有效。为什么会这样?我想这个问题有点奇怪,问为什么代码有效:)
编辑
即使在 gcc5 和 gcc HEAD 6.0.0 中,代码也会继续编译。