“ constexpr”变量“用于其自身的初始化程序”:Clang vs. GCC [英] `constexpr` variable "used in its own initializer": Clang vs. GCC

查看:96
本文介绍了“ constexpr”变量“用于其自身的初始化程序”:Clang vs. GCC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题似乎与现有的问题有关,但是我不理解答案(涉及 const auto this_ = this; ),而且我认为以下示例更容易理解。

This question seems related to an existing one, but I do not understand the "portable workaround" provided in the answer there (involving const auto this_ = this;) and moreover I think the following example is easier to follow.

我正在使用以下C ++ 17代码段(实时演示):

I am playing with the following snippet of C++17 code (live demo):

#include <iostream>

struct Test {
  const char* name_{nullptr};
  const Test* src_{nullptr};

  constexpr Test(const char* name) noexcept
    : name_{name}
  {}

  constexpr Test(const Test& src) noexcept
    : src_{&src}
  {
    name_ = src_->name_;
    src_ = nullptr;
  }
};

template<char c>
void print_constexpr_char() {
    std::cout << c << std::endl;
}

int main() {
  constexpr const char* in = "x";
  constexpr auto foo = Test{in};
  constexpr auto bar = Test{foo};
  std::cout << bar.name_ << std::endl;

  print_constexpr_char<bar.name_[0]>();

  return 0;
}

在GCC 7.2中编译失败,而Clang 5.0.0则看不到任何问题。 GCC错误本质上是

Compilation fails with GCC 7.2 while Clang 5.0.0 does not see any problem. The GCC error essentially reads


错误:'bar'的值不能在常量表达式中使用

error: the value of 'bar' is not usable in a constant expression

注意:在自己的初始化程序中使用的'bar'

note: 'bar' used in its own initializer

在意识到删除了final print_constexpr_char 使代码编译,尽管它仍包含GCC使用的行 constexpr auto bar = Test {foo}; 抱怨(用在它自己的初始化程序中)。

I am even more confused after realizing that removing the final print_constexpr_char makes the code compile although it still contains the line constexpr auto bar = Test{foo}; which GCC used to complain about ("used in its own initializer").


  1. 哪个编译器在这里正确?

  2. 如何理解GCC说明(如果不是bug),如果随后在常量表达式中使用结果,则在其自身的初始化程序中使用是有害的吗?

  3. 是否存在有效的在 constexpr 构造函数中使用指针作为中间阶段的方式/解决方法,然后将正在构造的对象转换为可以存储在 constexpr中的最终状态变量?

  1. Which compiler is correct here?
  2. How to understand the GCC note (if not a bug) that "using in its own initializer" is harmful iff the result is subsequently used in a constant expression?
  3. Is there a valid way/workaround to use pointers in a constexpr constructor as an intermediate stage before transforming the object under construction into the final state which can be stored in a constexpr variable?


推荐答案

GCC拒绝代码是正确的(但是错误消息可能会起作用)。除非该变量具有静态存储持续时间,否则无法在常量表达式中使用该变量的地址。

GCC is correct to reject the code (however the error message could use some work). You cannot use the address of a variable in a constant expression unless that variable has static storage duration.

foo 为不是静态的。如果将其移至 main 之外,则一切正常。 演示

foo is not static. If you move it outside of main, things will work. Demo

下面标记的行是问题所在:

The line marked below is the problem:

constexpr Test(const Test& src) noexcept
: src_{&src} <--- That

标准参考:(强调我的)

[expr.const]

[expr.const]


一个常量表达式要么是glvalue核心常量表达式,指的是一个实体,该实体是一个常量表达式(定义如下)的允许的
结果,或者是一个值满足以下条件的
的prvalue核心常量表达式:




(5.2)-如果值是指针类型,则它包含具有静态存储持续时间的对象的地址,即
超出此类对象末尾的地址(8.7),函数的地址或空指针值,

A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints:

(5.2) — if the value is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object (8.7), the address of a function, or a null pointer value,

这篇关于“ constexpr”变量“用于其自身的初始化程序”:Clang vs. GCC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆