constexpr with std::array - "Non-type template argument is not a constant expression"

constexpr with std::array - "Non-type template argument is not a constant expression"

本文关键字:expression is not argument constant Non-type std with array constexpr template      更新时间:2023-10-16

我正在尝试实现以下内容:

#include <array>
#include <cstdint>
class Class2
{
};
class Class1
{
public:
    static constexpr uint8_t GetMax() { return 5; }
    static constexpr uint8_t GetMin() { return 0; }
    static constexpr uint8_t GetCount() { return GetMax() - GetMin() + 1; }
private:
    std::array<Class2, Class1::GetCount()> m_classes;
};

但是由于错误,我无法让它工作:

非类型模板参数不是常量表达式

我正在使用Xcode 5.0。有什么想法吗?

我们在这里遇到的问题在 3.3.7 中间接描述 - 类范围:

typedef int c;
enum { i = 1 };
class X {
    char v[i]; // error: i refers to ::i
               // but when reevaluated is X::i
    int f() { return sizeof(c); } // OK: X::c
    char c;
    enum { i = 2 };
};

这一段应该更多地描述这一点(9.2.2):

在类说明符的结尾 } 处被视为完全定义的对象类型 (3.9)(或完整类型)。在类成员规范中,类在函数体、默认参数、异常规范和非静态数据成员(包括嵌套类中的此类内容)的大括号或等于初始值设定项中被视为完整的。否则,它在其自己的类成员规范中被视为不完整。

由于std::array<Class2, Class1::GetCount()>既不是函数体、默认参数、异常规范、大括号或等于初始值设定项,在这一点上,类被认为是不完整的,所以我认为由编译器决定何时允许这样做,或者不允许这样做 - 但按照标准不编译代码是可以的。

我能想到的唯一解决方案是您建议的解决方案,或者将 constexprs 移动到另一个(可能的基)类中。

按照Nemanja Boric的回答,我将静态方法转换为静态成员。这不是我想要的修复程序,但它有效。我想剩下的问题是为什么它不起作用?

#include <array>
#include <cstdint>
class Class2
{
};
class Class1
{
public:
    static constexpr uint8_t Max = 5;
    static constexpr uint8_t Min = 0;
    static constexpr uint8_t Count = Max - Min + 1;
private:
    std::array<Class2, Class1::Count> m_classes;
};