#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).
以上是内存溢出为你收集整理的根据C 14,未使用的函数是否可以实例化具有副作用的变量模板?全部内容,希望文章能够帮你解决根据C 14,未使用的函数是否可以实例化具有副作用的变量模板?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)