代码之家  ›  专栏  ›  技术社区  ›  Jeremy Friesner

为什么constexpr属性在应用于静态方法时不起作用?[副本]

  •  5
  • Jeremy Friesner  · 技术社区  · 8 年前

    考虑一下这个微不足道的测试代码:

    class Test
    {
    public:
       Test() {/* empty */}
    
    private:
       enum {BLAH = 42};
    
       static constexpr int Magic() {return BLAH*4;}
    
       float f[Magic()];
    };
    
    int main(int argc, char ** argv)
    {
       Test t;
       return 0;
    }
    

    当我尝试编译它时(在MacOS/X下使用最新XCode中的clang++),我得到了以下编译器错误:

    Jeremys-Mac-Pro:~ jaf$ clang++ -std=c++11 ./test.cpp
    ./test.cpp:11:14: error: fields must have a constant size: 'variable length
          array in structure' extension will never be supported
           float f[Magic()];
    

    有人能解释为什么这是一个错误吗?作为比较,如果我将Magic()方法移出测试类并使其成为一个独立的函数,它会按照预期进行编译,但我真的不想这样做,因为我希望尽可能将Magic()和BLAH保持为测试类的私有。

    (注意:这里我并没有试图使用可变长度数组;相反,我试图声明一个数组,其大小由编译时的函数计算决定)

    1 回复  |  直到 8 年前
        1
  •  3
  •   Myria    8 年前

    这是因为类中的函数直到类完成后才被处理。此规则允许在类中定义的函数访问该类的成员,这些成员在类中定义的时间晚于该函数。因此 Magic() 还没有定义,因此无法在编译时进行计算。

    这是正确的行为,尽管各种编译器生成的错误对理解问题没有帮助。

    形式规则在C++标准的[class.member]/6中:

    在结束时,类被视为完全定义的对象类型(6.9)(或完全类型) } 的 类说明符 . 在课堂上 构件规范 ,类在函数体、默认参数和, 无异常说明符 和默认成员初始值设定项(包括嵌套类中的此类内容)。否则,它在其自己的类中被视为不完整的 构件规范 .