为什么这个虚拟 constexpr 函数不被识别为常量?

use*_*734 4 c++ inheritance visual-c++ c++20

我有以下使用virtual constexprC++20 的示例代码,但无法编译:

enum legCount {
    APODA = 0,
    BIPEDAL = 2,
    QUADRUPEDAL = 4,
};

class Animal {
public:
    constexpr virtual legCount getLegCount() = 0;
};

class Tiger : public Animal {
public:
    constexpr legCount getLegCount() { return QUADRUPEDAL; }

    void manipulateLegsArray() {
        unsigned char arr[getLegCount()];
    }
};
Run Code Online (Sandbox Code Playgroud)

该代码使用 Clang 进行编译,但 MSVC 抱怨getLegCountin 的unsigned char arr[getLegCount()];计算结果不为常量表达式(失败是由于在其生命周期之外读取变量引起的)。MSVC 在这里是否正确?如果正确,这是为什么?

此外,我如何以一致的方式模仿此功能?我想要一个抽象基类,其中所有派生类都必须实现该函数,并且该函数必须是 constexpr。

确切的编译器错误消息如下:

D:\Projects\temp\demo\main.cpp(17,32): error C2131: expression did not evaluate to a constant [D:\Projects\temp\out\demo\demo.vcxproj]
D:\Projects\temp\demo\main.cpp(17,21): message : failure was caused by a read of a variable outside its lifetime [D:\Projects\temp\out\demo\demo.vcxproj]
D:\Projects\temp\demo\main.cpp(17,21): message : see usage of 'this' [D:\Projects\temp\out\demo\demo.vcxproj]
Run Code Online (Sandbox Code Playgroud)

Ahm*_*AEK 5

manipulateLegsArray函数可以在运行时被继承自你的类的另一个类调用,因此getLegCount()必须在运行时解析,你的数组现在变成了变长数组,MSVC不支持,只有clang/gcc支持。

您可以强制派生类使用 CRTP 实现 constexpr 的某些内容。

enum legCount {
    APODA = 0,
    BIPEDAL = 2,
    QUADRUPEDAL = 4,
};

template< typename T>
class Animal {
public:
    static constexpr legCount getLegCount()
    {
        return T::legCount_v;
    }
};

class Tiger : public Animal<Tiger> {
public:
    constexpr static legCount legCount_v = QUADRUPEDAL;

    void manipulateLegsArray() {
        unsigned char arr[getLegCount()];
    }
};
Run Code Online (Sandbox Code Playgroud)