【问题标题】:clang says call to void consteval function is not a constant expressionclang 说调用 void consteval 函数不是常量表达式
【发布时间】:2020-12-01 12:24:50
【问题描述】:

clang(trunk) 给出以下代码的错误:

consteval void f() {}

int main() 
{ 
    f();  // error: call to consteval function 'f' is not a constant expression
          // note: subobject of type 'void' is not initialized
}

而 gcc(trunk) 编译它没有错误。

我觉得这可能是一个clang错误,因为gcc和clang都接受这个代码:

consteval int g() { return 42; }

int main() 
{ 
    g();  // ok
}

这是code 玩。

那么这是一个clang错误,还是代码格式错误,或者有ub,或者其他什么?


编辑:我觉得有必要指出 clang 允许从其他函数调用 f,如果它们也是 consteval 的话。仅当从非 consteval 函数调用 f 时才会出现错误:

consteval int h() 
{ 
    f();       // ok
    return 42; 
}

demo.

【问题讨论】:

  • 如果 f 是 constexpr 是否有效? (强制 constexpr 时,如 constexpr int x = (f(), 5);
  • @Dani 不,它给出了相同的error
  • @Barry True,但我的印象是它已经在主干中实施了一段时间。那么它只是一个不完整的功能呢?不过仍然是一个奇怪的错误。
  • 那么我会说这是一个编译器错误。例如,理由是std::sort

标签: c++ language-lawyer c++20 constant-expression consteval


【解决方案1】:

这是一个 Clang 错误,在版本 10 和版本 11 之间以及上个月的fixed 之间引入。 consteval 在 Clang 中的实现大部分但不完全是完整的,这个错误是在其中一个补丁添加更完整的 consteval 支持之后出现的。

详细信息:Clang 的常量评估器的顶级入口点检查结果是否是常量表达式的允许结果——它检查结果不包含指向自动存储持续时间或临时或类似的指针。但是此检查从未更新以适应 void 作为文字类型,并且会拒绝 void 类型的值因为“未初始化”。在添加 consteval 支持之前从未注意到这一点,因为所有顶级常量评估都是非 void 类型的。

【讨论】:

【解决方案2】:

我发现c++20 final draft是:

9.2.5 constexpr 和 constevals 修饰符[dcl.constexpr] (2) 函数声明中使用的 constexpr 或 consteval 说明符将该函数声明为 constexpr 函数。使用 consteval 说明符声明的函数或构造函数称为动画函数。析构函数、分配函数或释放函数不得使用 consteval 说明符声明。

(3) constexpr 函数的定义应满足以下要求:

3.1 它的返回类型(如果有的话)应该是一个字面量类型;

6.8 类型 [basic.types]

(10) 一个类型是文字类型,如果它是:

(10.1) 简历无效

...

因为 voidconsteval 函数的有效返回类型。

【讨论】:

  • “如果有”似乎使 void 在这里有效。“如果有”涵盖了构造函数和析构函数没有返回类型。 void f(); 确实有返回类型。 «cv void» 是 literal type,“如果有的话”不适合它。
  • @LanguageLawyer:感谢您的解释。这使得 void 成为 conexpr/consteval 函数的有效返回类型。
  • @LanguageLawyer 如何构造void 的对象?它实际上从 K&R 那里得到了这个名字,因为它什么都不是。我想这就是 clang 的架构失败的地方
  • 其实我不怀疑f的定义是好的。问题是关于呼叫f(),这是错误的来源。请注意,clang 允许从其他 consteval 函数调用 fdemo.
  • "if any" 涵盖了构造函数和析构函数没有返回类型 其实只有构造函数没有,析构函数不允许是consteval
猜你喜欢
  • 1970-01-01
  • 2022-10-23
  • 1970-01-01
  • 2021-09-15
  • 2017-03-30
  • 1970-01-01
  • 2015-06-15
  • 1970-01-01
相关资源
最近更新 更多