当获取一个地址时,模板类型(类/函数)的实例化规则是什么?
What are the rules around instantiation of template types (class/function) when taking an address?
在回答这个问题时,我遇到了模板实例化方面的行为差异。
最初有一个函数模板
template <typename T> void my_callback(void* data) { … }
现在有些东西需要这个的地址-特别是void*
,所以明显的方法是
bar(reinterpret_cast<void*>(&my_callback<int>));
然而,在gcc 4.5之前的编译器版本中,由于上下文不够,这将失败…错误。很好——所以修复是先"cast"——强制实例化,即:
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;
}
};
现在,原来的reinterpret_cast
工作良好。
bar(reinterpret_cast<void*>(&foo<int>::my_callback));
所以我的问题是——为什么这种明显的行为差异?
From n3290, 14.7.1隐式实例化[temp.inst]
在第1段中对于类模板特化也有类似的规则。请注意,标准提到了专门化,因为专门化是在使用模板时隐式声明的,这里没有用户提供的专门化,至少对于函数模板(第8段)。2除非函数模板专门化已被显式地实例化或显式特化的函数模板当专门化时,将隐式实例化专门化在需要存在函数定义的上下文中引用。
与第10段结合,
实现不应该隐式地实例化函数模板,成员模板,非虚成员函数,成员类的静态数据成员或类模板的静态数据成员需要实例化。
我认为经验法则是:只要需要对象/类成员/函数或使程序正常工作(非正式地说),模板就会隐式实例化,但是不会早于。这包括获取函数的地址。
关于你所链接的问题,reinterpret_cast
的某些使用可能会使程序不符合标准,到那时就不需要提及实例化了——我邀请你看看我在那里的答案<<b>/shameless>。
相关文章:
- 如何使用非默认构造函数实例化模板化类
- C++ - 使用另一个类的构造函数实例化一个对象
- 与参数匹配的友元模板函数实例化
- 在保证复制的世界中构造函数实例化
- SFINAE 和模板函数实例化:为什么在启用了 SFINAE 类型的函数参数中使用模板参数时无法推断模板参数?
- 防止复制构造函数实例化 C++11 类"deleting"
- 如何键入定义一个专门的 std::set 模板,使用特定的比较函数实例化
- 使用不同类型的模板函数实例化
- C 调用模板构造函数实例化
- 为什么很清楚模板函数实例化不会内联
- 模板函数实例化文件
- 模板函数实例化的可移植性问题
- 模板函数实例化 自定义数据类型的问题
- 模板类成员函数实例化
- C++.对象使用错误的构造函数实例化
- C++如何用参数化构造函数实例化对象
- 为什么无法使用复制构造函数实例化"non const"而可以在没有复制构造函数的情况下实例化配对?
- 双模板化函数实例化失败
- 延迟 crtp 基类中的成员函数实例化
- 如何根据容器的元素类型启用模板函数实例化