为什么约束函数允许未定义的行为?

时间:2019-10-18 16:14:57

标签: c++ undefined-behavior c++20 consteval

C ++中的常量表达式具有非常整洁的特性:它们的求值不能具有未定义的行为(7.7.4.7):

  

表达式e是核心常量表达式,除非按照抽象机([intro.execution])的规则对e求值将对以下之一进行求值:

     
      
  • ...

  •   
  • 一种操作,该操作将具有本文档[intro]至[cpp]中指定的未定义行为[注意:例如,包括带符号整数溢出([expr.prop]),某些指针算术([ expr.add]),除以零或某些移位操作-尾注];

  •   

尝试将13!的值存储在yields a nice compile errorconstexpr int中:

constexpr int f(int n) 
{
    int r = n--;
    for (; n > 1; --n) r *= n;
    return r;
}

int main() 
{
    constexpr int x = f(13);
    return x;
}

输出:

9:19: error: constexpr variable 'x' must be initialized by a constant expression
    constexpr int x = f(13);
                  ^   ~~~~~
4:26: note: value 3113510400 is outside the range of representable values of type 'int'
    for (; n > 1; --n) r *= n;
                         ^
9:23: note: in call to 'f(3)'
    constexpr int x = f(13);
                      ^
1 error generated.

(顺便说一句,为什么错误是“调用'f(3)'”,而它却是对f(13)的调用?。)

然后,我从constexpr中删除x,但将f设为consteval。根据{{​​3}}:

  

consteval-指定一个函数为立即函数,也就是说,对该函数的每次调用都必须产生一个编译时常量

我确实希望这样的程序会再次导致编译错误。而是the docs

那是为什么?

UPD:评论者建议这是一个编译器错误。我报告了它:the program compiles and runs with UB

1 个答案:

答案 0 :(得分:2)

这是一个编译器错误。或者,更确切地说,这是一个“未实现的”功能(请参见the comment in bugzilla):

  

是的-根据https://clang.llvm.org/cxx_status.html

     

(可能已添加了关键字,但未添加实际的实现支持)