Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ constexpr和可变成员以及隐式复制构造函数_C++_Language Lawyer_C++17_Copy Constructor_Constexpr - Fatal编程技术网

C++ constexpr和可变成员以及隐式复制构造函数

C++ constexpr和可变成员以及隐式复制构造函数,c++,language-lawyer,c++17,copy-constructor,constexpr,C++,Language Lawyer,C++17,Copy Constructor,Constexpr,下面的代码是用clang7+编译的,但不是用5&6(用c++17和c++14)编译的。 clang 5和6的问题似乎是隐式复制ctor读取可变成员x 有人能告诉我,整个结构是符合标准的(c++17),还是程序格式不正确?或者,关于隐式复制ctor的标准是否有变化,而在早期的clang版本中可能没有实现 struct Foo { int a; mutable int x{}; constexpr Foo() : a(0) {} //constexpr Foo(

下面的代码是用clang7+编译的,但不是用5&6(用c++17和c++14)编译的。 clang 5和6的问题似乎是隐式复制ctor读取可变成员
x

有人能告诉我,整个结构是符合标准的(c++17),还是程序格式不正确?或者,关于隐式复制ctor的标准是否有变化,而在早期的clang版本中可能没有实现

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;
}
structfoo{
INTA;
可变int x{};
constexpr Foo():a(0){}

//constexpr-Foo(const-Foo&other):a(other.a){}/代码格式不正确。以下是简化的代码,在所有编译器上都会失败:

struct Foo {
    int a;
    mutable int x{};
    constexpr Foo() : a(0) {}

};

int main() {
    constexpr Foo f;
    constexpr Foo f1 = f;
}
根据[expr.const]7.7

变量在初始化后可以在常量表达式中使用 如果 它是一个constexpr变量

或者…(3.5)一个不可变的 上述任何一项的子对象或引用成员


这将取消默认复制构造函数的资格。

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

constexpr int f(int i) {
  int j=i;
  ++j;
  return i+j;  // neither is a constant expression
}
问题是,在常量表达式中检查的任何内容都必须是常量,或者在表达式求值期间开始其生存期。在您的情况下,
create
f.x
的生存期显然是在常量表达式的求值范围内开始的,该常量表达式是表达式的初始化
main
f
。但是,确实,不创建该对象的常量表达式不能复制任何
Foo
对象,无论该对象是否为
constexpr


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

Clang可能不会抱怨OP的代码,因为NRVO起作用了。添加
constexpr Foo f1=f;
确实会导致错误。很好的捕获,这似乎就是原因!谢谢大家!这个简单阳离子似乎并不等效。不要求
constexpr
函数只使用常量表达式。在我看来,原始工厂函数调用
Foo
的默认构造函数来生成
f
,然后用复制构造函数初始化其返回对象。这两个函数都不要求
f
在c中可用onstant表达式。初始化
constepr Foo f=FooFactory::create()
不会直接调用任何构造函数。
f
通过调用的求值来初始化。因此,
f
初始化的完整表达式只是对
constepr
函数的调用,这是允许的。这就是[expr.const]/3,不是7.7,是C++20草稿的一部分,不是17,项目符号不对应变量,而是对象或引用。非常有趣,谢谢。我提到了一个非常量成员的读取,因为这是this-is-not-a-constant-expression-error之后的note clang 6 printet。