在回答这个问题时,我在模板实例化方面遇到了这种行为差异.
最初有一个功能模板
template <typename T> void my_callback(void* data) { … }
Run Code Online (Sandbox Code Playgroud)
现在有些东西需要这个地址 - 特别是a void*,所以显而易见的方法是
bar(reinterpret_cast<void*>(&my_callback<int>));
Run Code Online (Sandbox Code Playgroud)
但是,对于gcc 4.5之前的编译器版本,这会导致上下文错误...错误.好 - 所以修复是先"强制转换" - 强制实例化,即:
void (*callback)(void*) = my_callback<int>;
bar(reinterpret_cast<void*>(callback));
Run Code Online (Sandbox Code Playgroud)
这很好用.
现在是第二种情况,它不是一个自由函数,而是一个类模板的静态成员,即
template <typename T>
struct foo
{
static void my_callback(void* data) {
T& x = *static_cast<T*>(data);
std:: cout << "Call[T] with " << x << std::endl;
}
};
Run Code Online (Sandbox Code Playgroud)
现在,原作reinterpret_cast好了.
bar(reinterpret_cast<void*>(&foo<int>::my_callback));
Run Code Online (Sandbox Code Playgroud)
所以我的问题是 - 为什么这种明显的行为差异?
来自 n3290,14.7.1 隐式实例化 [temp.inst]
2 除非函数模板特化已被显式实例化或显式特化,否则当在需要函数定义存在的上下文中引用该特化时,该函数模板特化将被隐式实例化。
第 1 段中对于类模板特化也有类似的规则。请注意,该标准是用专业化来表述的,因为在使用模板时会隐式声明专业化,这里没有用户提供的专业化,至少对于函数模板而言(第 8 段)。
结合第10段,
10 实现不得隐式实例化不需要实例化的函数模板、成员模板、非虚成员函数、成员类或类模板的静态数据成员。
我认为经验法则是:一旦需要对象/类成员/函数或使程序正常工作(非正式地说),模板就会隐式实例化,但不会更快。这包括获取函数的地址。
至于您链接的问题,某些使用reinterpret_cast可能会使程序不符合要求,此时提及实例化已经无关紧要了——我邀请您在那里查看我的答案</无耻>。