获取函数模板的地址时隐式实例化
Implicit instantiation of function templates when taking their address
注意:我已经看了这里,我不认为答案是正确的。
在获取地址时,控制函数隐式实例化的规则是什么?14.7.1/9的n3242这样说:
实现不应隐式实例化不需要实例化的函数模板、成员模板、非虚成员函数、成员类或类模板的静态数据成员。
现在,当然不需要有一个函数定义来获取它的地址。我们可以采用前向声明函数的地址,并将它们定义在不同的翻译单元中。
既然如此,我不知道什么时候需要。然而,编译器似乎有自己的想法。在GCC和VC上测试,这里有几个例子:
template <typename T> void CallBanana() { T::Banana(); }
template <typename T> void CallUnimpl();
template <typename T>
struct S {
static void CallBanana() { T::Banana(); }
static void CallOrange() { T::Orange(); }
static void CallUnimpl();
};
struct B { static void Banana() {} };
int main() {
(void)(&CallBanana<void>); // 1
(void)(&CallUnimpl<void>); // 2
(void)(&S<void>::CallBanana); // 3
(void)(&S<void>::CallOrange); // 4
(void)(&S<void>::CallUnimpl); // 5
(void)(&S<B>::CallBanana); // 6
}
应该一次注释一个,以查看效果。
这里测试的GCC 4.7会报错1、3和4。因此,它将实例化所有存在的定义。
VC 2010(没有在线测试,抱歉)实例化了3和4,但没有实例化1。
Clang 3.0在这里测试的行为与VC 2010相同。
没有编译器抱怨2或5,这是我所期望的。如果我真的使用了这些指针,我希望它链接失败。
在所有编译器上,6个编译器。我预料到这一点,但它的目的是表明,仅仅因为我取了单个函数的地址,整个类模板就没有被实例化(正如在另一个问题的答案中所声称的那样)。如果整个模板都被实例化了,那么S::CallOrange不应该被编译,因为B不包含Orange函数。
所以我想知道是否有人有一个明确的答案,正确的行为应该是什么。标准似乎声称不应该实例化函数,然而三种流行的编译器在某些情况下实例化,但彼此也不同。
如果取函数的地址(在求值的上下文中),则需要函数的定义
当然,定义可以在单独的翻译单元中给出,但这并不能改变需要定义的事实。
如果只需要一个成员函数,并不意味着也要实例化其他成员函数。
如果函数模板未定义,则不能隐式实例化。然后必须在另一个翻译单元中显式地实例化它。不允许依赖于另一个翻译单元中的隐式实例化(但不需要诊断)。
需要进行实例化,因为扩展模板可能无法生成格式良好的代码。
事实上,实例化甚至可能不会产生一个有效的原型(这种失败将被限定为"不失败")。
(当涉及到SFINAE时,所取的有效地址可能会在部分排序中忽略几个较早的候选者(因为替代失败不是错误),然后才选择实际候选者来取。的地址)
- 从C++实例化QML
- 设计一个只能由特定类实例化的类(如果可能的话,通过make_unique)
- 如何创建一个空的全局类并在启动时实例化它
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 约束和显式模板实例化
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 对象实例化调用构造函数的次数太多
- 如何使用非默认构造函数实例化模板化类
- 静态数据成员模板专用化的实例化点在哪里
- 错误的cv::face FacemarkLBF实例化
- C++的解析器在可以区分比较和模板实例化之前会做什么?
- 为什么 gcc 和 clang 为函数模板的实例化生成不同的符号名称?
- 检查某些类型是否是模板类 std::optional 的实例化
- 我有一个对象,它将在整个程序的持续时间内实例化,但一个类成员不会,我应该动态分配它吗?
- 无法使用 SWIG 在 Python 中实例化C++类(获取属性错误)
- 获取模板类对象的地址将导致模板参数的完全实例化
- 使LLDB将地址重新解释为指向模板实例化类型对象的指针
- 获取函数模板的地址时隐式实例化
- 跨编译单元的相同函数模板实例化的地址
- 当获取一个地址时,模板类型(类/函数)的实例化规则是什么?