根据C 14,未使用的函数是否可以实例化具有副作用的变量模板?
作者:互联网
这是我的代码:
#include <iostream>
class MyBaseClass
{
public:
static int StaticInt;
};
int MyBaseClass::StaticInt = 0;
template <int N> class MyClassT : public MyBaseClass
{
public:
MyClassT()
{
StaticInt = N;
};
};
template <int N> static MyClassT<N> AnchorObjT = {};
class UserClass
{
friend void fn()
{
std::cout << "in fn()" << std::endl; //this never runs
(void)AnchorObjT<123>;
};
};
int main()
{
std::cout << MyBaseClass::StaticInt << std::endl;
return 0;
}
输出是:
123
…表示调用了MyClassT()构造函数,尽管从未调用过fn().
在gcc和clang上测试-O0,-O3,-Os甚至-Ofast
题
根据C标准,此程序是否具有未定义的行为?
换句话说:如果更高版本的编译器设法检测到永远不会调用fn(),那么它们是否可以在运行构造函数的同时优化模板实例化?
这个代码可以以某种方式确定性,即强制构造函数运行 – 不引用函数名称fn或UserClass之外的模板参数值123吗?
更新:主持人截断了我的问题并建议进一步截断.原始详细版本可以查看here.
解决方法:
模板实例化是代码的函数,而不是任何类型的动态运行时条件的函数.作为一个简单的例子:
template <typename T> void bar();
void foo(bool b) {
if (b) {
bar<int>();
} else {
bar<double>();
}
}
bar< int>和bar< double>在这里实例化,即使永远不会调用foo,或者即使foo只用true调用.
对于变量模板,具体来说,规则是[temp.inst]/6:
Unless a variable template specialization has been explicitly instantiated or explicitly specialized, the variable template specialization is implicitly instantiated when it is referenced in a context that requires a variable definition to exist or if the existence of the definition affects the semantics of the program.
在你的功能:
06001
AnchorObjT< 123>在需要定义的上下文中引用(无论是否调用fn(),甚至在这种情况下,甚至可以调用),因此它被实例化.
但是AnchorObjT< 123>是一个全局变量,所以它的实例化意味着我们有一个在main()之前构造的对象 – 当我们输入main()时,AnchorObjT< 123>的构造函数将被运行,将StaticInt设置为123.注意我们不需要实际运行fn()来调用这个构造函数 – 这里的fn()角色只是实例化变量模板,其构造函数在别处被调用.
打印123是正确的预期行为.
注意,虽然该语言需要全局对象AnchorObjT< 123>要存在,链接器仍然可以是对象,因为没有对它的引用.假设你的真实程序对这个对象有更多的作用,如果你需要它存在,你可能需要做更多的事情来防止链接器删除它(例如gcc有used
attribute).
标签:unused-variables,c,templates,c14,standards 来源: https://codeday.me/bug/20190731/1586160.html