【问题标题】:Could non-static member variable be modified in constexpr constructor (C++14)?可以在 constexpr 构造函数(C++14)中修改非静态成员变量吗?
【发布时间】:2014-05-14 06:47:26
【问题描述】:
struct A {
    int a = 0;
    constexpr A() { a = 1; }
};

constexpr bool f() {
    constexpr A a;
    static_assert(a.a == 1, ""); // L1: OK
    return a.a == 1;
}
static_assert(f(), ""); // L2: Error, can not modify A::a in constexpr
  • 在线编译器 URL:http://goo.gl/jni6Em
  • 编译器:clang 3.4(使用 -std=c++1y)
  • 系统:Linux 3.2

如果我删除 L2,此代码将编译。如果我添加 L2,编译器会抱怨“在常量表达式中不允许修改 const 限定类型 'const int' 的对象”。我不是语言律师,所以我不确定这是否属实。但是,如果是,为什么编译器没有抱怨 L1,因为它也将 A() 称为 constexpr?这是clang的错误吗?还是我错过了什么?

参考:http://en.cppreference.com/w/cpp/language/constexpr

顺便说一句,如果我更改“constexpr A a;”到“一个;” (删除 constexpr 关键字),L1 编译失败,这是预期的。但是,编译器不再抱怨 L2。

在线编译器网址:http://goo.gl/AoTzYx

【问题讨论】:

    标签: c++ constexpr c++14


    【解决方案1】:

    我相信这只是编译器没有赶上为 C++14 提议的更改的一个例子。您的constexpr 构造函数满足N3936 的§7.1.5/4 中列出的所有条件。 gcc and clang fail to compile 你的代码,但是出于不同的原因。

    clang 抱怨:

    注意:常量表达式中不允许修改 const 限定类型“const int”的对象

    这没有多大意义,但让我想起了 C++11 限制 constexpr 成员函数隐式为 const (这是一个构造函数,不适用,但错误消息是让人想起那个)。 C++14 也解除了这个限制。

    gcc 的错误信息是:

    错误:constexpr 构造函数没有空体

    似乎很清楚 gcc 仍然为 constexpr 构造函数实现 C++11 规则。

    此外,N3597 列出了这个例子:

    struct override_raii {
      constexpr override_raii(int &a, int v) : a(a), old(a) {
        a = v;
      }
      constexpr ~override_raii() {
        a = old;
      }
      int &a, old;
    };
    

    N3597 已被 N3652 取代,其中包含当前草案中的措辞。不幸的是,前面的例子消失了,但是,再一次,当前的措辞中没有任何内容表明您不能将值分配给 constexpr 构造函数体内的数据成员。

    更新 (2017-10-03)

    clang 修复了这个问题,但还没有新版本:https://bugs.llvm.org/show_bug.cgi?id=19741 (Compiler explorer)

    【讨论】:

    • 使用初始化语法而不是在构造函数的函数体中分配 A::a 会有所帮助吗?
    • @NHDaly 是的,当然。在这种情况下,clang 成功编译了代码。 gcc 仍然失败,因为 f() 不满足 constexpr 函数的 C++11 要求。这里的问题在构造函数体中数据成员的赋值。
    • 那只是因为 gcc 还没有赶上 C++14,是吗?
    • @NHDaly 看起来是这样,至少在放松的时候constexpr
    • 我看不出这个例子是如何应用的......它没有为构造函数主体中的数据成员赋值,因为a 是一个引用,不是吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-03
    • 1970-01-01
    • 2014-03-14
    相关资源
    最近更新 更多