首页 > 解决方案 > constexpr 和 mutable 成员和隐式 copy-ctor

问题描述

以下代码在 clang 7+ 中编译,但不在 5 和 6 中编译(使用 c++17 和 c++14)。clang 5 和 6 的问题似乎是隐式复制 ctor 从 mutable member 读取x

谁能告诉我,整个结构是否符合标准(c++17),或者程序是否格式错误?还是在早期的 clang 版本中可能无法实现的隐式复制ctor 的标准发生了变化?

struct Foo {

    int a;
    mutable int x{};

    constexpr Foo() : a(0) {}

    //constexpr Foo(const Foo& other) : a(other.a) {} // <- with this line it works on Clang 5 & 6, too
};

struct FooFactory {

    static constexpr auto create() {
        auto f = Foo{};       
        return f;
    }
};

int main() {

    constexpr Foo f = FooFactory::create();
    ++f.x;
}

现场代码在这里

标签: c++language-lawyerc++17copy-constructorconstexpr

解决方案


这是一个格式良好的 C++17 程序。constexpr 函数当然可以读取(和写入)非常量变量:

constexpr int f(int i) {
  int j=i;
  ++j;
  return i+j;  // neither is a constant expression
}

规则是,在常量表达式中检查的任何内容都必须是常量,或者在表达式求值期间开始其生命周期。在您的情况下,create's的生命周期f.x显然始于对常量表达式的评估,即's的初始化。然而,确实没有对象可以被不创建该对象的常量表达式复制,无论它是否是.mainfFooconstexpr

唯一的其他候选问题是如果复制构造函数不是 constexpr,但这些要求非常。唯一相关的是每个(非变体)成员都被初始化,这肯定是令人满意的,并且它可以在至少一个常量表达式中使用,这已经被证明了。


推荐阅读