C++ 获取地址时,模板类型(类/函数)实例化的规则是什么?

C++ 获取地址时,模板类型(类/函数)实例化的规则是什么?,c++,templates,C++,Templates,在回答这个问题时,我遇到了关于模板实例化的这种行为差异 最初有一个函数模板 template <typename T> void my_callback(void* data) { … } 但是,在GCC4.5之前的编译器版本中,如果上下文不够,则会失败。。。错误。很好-因此修复方法是先“强制”转换-强制实例化,即: void (*callback)(void*) = my_callback<int>; bar(reinterpret_cast<void*>

在回答这个问题时,我遇到了关于模板实例化的这种行为差异

最初有一个函数模板

template <typename T> void my_callback(void* data) { … }
但是,在GCC4.5之前的编译器版本中,如果上下文不够,则会失败。。。错误。很好-因此修复方法是先“强制”转换-强制实例化,即:

void (*callback)(void*) = my_callback<int>;
bar(reinterpret_cast<void*>(callback));

所以我的问题是-为什么行为上会有这种明显的差异?

来自n3290,14.7.1隐式实例化[temp.inst]

2除非明确指定了函数模板专用化 实例化或显式专用化的函数模板 专门化是在指定专门化时隐式实例化的 在需要函数定义存在的上下文中引用

第1段中有类似的类模板专门化规则。请注意,该标准以专门化的形式表述,因为当使用模板时,专门化是隐式声明的,这里没有用户提供的专门化,至少对于函数模板(第8段)

结合第10段

10实现不应隐式实例化函数 模板、成员模板、非虚拟成员函数、成员 类或类模板的静态数据成员 需要实例化

我认为经验法则是:只要需要一个对象/类成员/函数,或者让程序以其他方式工作(非正式地说),模板就会隐式实例化,但不会很快。这包括获取函数的地址


至于您所链接的问题,使用
reinterpret\u cast
可能会使程序不一致,此时不必提及实例化--.

因此,基本上,要获取成员的地址(即使是静态的),必须实例化类型--因此编译器将,但不是免费函数,因为它不需要。。。thx.@Nim:获取函数的地址需要函数定义(链接器将从中获取地址),因此获取模板函数的地址应该意味着该函数特定专门化的实例化。@David,是的,这就是我问的原因,为什么对的地址的重新解释对函数模板不起作用,tbh,我还没有像Luc的回答那样尝试过间接版本。@Nim它不起作用,因为它不需要。用C++0x的n3290草案的话说,从函数指针类型转换为对象指针类型是“有条件支持的”。我相信C++03提供的保证更少。。。借用我最近的一个问题:)+1,这个问题其实很有趣。
void (*callback)(void*) = my_callback<int>;
bar(reinterpret_cast<void*>(callback));
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;
  }
};
bar(reinterpret_cast<void*>(&foo<int>::my_callback));