【问题标题】:constexpr with std::array - "Non-type template argument is not a constant expression" [duplicate]带有 std::array 的 constexpr -“非类型模板参数不是常量表达式”[重复]
【发布时间】:2013-09-21 18:21:54
【问题描述】:

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

#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。有什么想法吗?

【问题讨论】:

  • 看起来你遇到了this
  • 我得到一个稍微不同的错误:“GetCount() 在其定义之前使用”。据推测,这是因为Class1 在其成员声明中不完整。但这不是答案,因为 (a) 我不确定,并且 (b) 我不知道如何解决。
  • @MikeSeymour 我认为你是对的,因为在 Class1 之外声明一个数组是有效的。但我想看看如何解决这个问题。
  • @MikeSeymour “成员声明不完整”是什么意思?据我所知,它是完整的。顺便说一句,这些方法不应该是内联的吗?
  • 这里的评论 (stackoverflow.com/questions/9789913/…) 应该是相关的:“嗯.. 我想我们之前刚刚讨论过这个:内联函数定义被视为就好像它们是在类定义之后定义的一样;所以在类定义中它们还不可用。请注意,您始终可以说 static const int number = 256; 或 static constexpr int number = 256; 代替。"

标签: c++ templates c++11 clang constexpr


【解决方案1】:

我们在这里遇到的问题在 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&lt;Class2, Class1::GetCount()&gt; 既不是函数体、默认参数、异常规范、大括号或相等初始化器,在这一点上,类被认为是不完整的,所以我认为这取决于编译器决定何时允许或不允许 - 但按照标准不编译代码是可以的。

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

【讨论】:

  • 感谢您的参考,这一切都清楚了。
【解决方案2】:

按照 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;
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-15
    • 2023-03-14
    • 1970-01-01
    • 2016-04-06
    • 1970-01-01
    • 2016-03-01
    相关资源
    最近更新 更多