当前位置 : 主页 > 编程语言 > c++ >

根据C 14,未使用的函数是否可以实例化具有副作用的变量模板?

来源:互联网 收集:自由互联 发布时间:2021-06-23
这是我的代码: #include iostreamclass 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
这是我的代码:

#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).

网友评论