为什么 consteval 函数允许未定义的行为?
Why does a consteval function allow undefined behavior?
C++ 中有一个非常整洁的常量表达式属性:它们的计算不能有未定义的行为(7.7.4.7):
An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following:
...
an operation that would have undefined behavior as specified in [intro] through [cpp] of this document [ Note: including, for example, signed integer overflow ([expr.prop]), certain pointer arithmetic ([expr.add]), division by zero, or certain shift operations — end note ] ;
试图将 13!
的值存储在 constexpr int
中确实 yields a nice compile error:
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) 的调用?..)
然后,我从 x
中删除 constexpr
,但将 f
设为 consteval
。根据 the docs:
consteval - specifies that a function is an immediate function, that is, every call to the function must produce a compile-time constant
我预计这样的程序会再次导致编译错误。但是,the program compiles and runs with UB.
这是为什么?
UPD: 评论者认为这是一个编译器错误。我举报了:https://bugs.llvm.org/show_bug.cgi?id=43714
这是一个编译器错误。或者,更准确地说,这是一个“未充分实现”的功能(参见 the comment in bugzilla):
Yup - seems consteval isn't implemented yet, according to: https://clang.llvm.org/cxx_status.html
(the keyword's probably been added but not the actual implementation support)
C++ 中有一个非常整洁的常量表达式属性:它们的计算不能有未定义的行为(7.7.4.7):
An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following:
...
an operation that would have undefined behavior as specified in [intro] through [cpp] of this document [ Note: including, for example, signed integer overflow ([expr.prop]), certain pointer arithmetic ([expr.add]), division by zero, or certain shift operations — end note ] ;
试图将 13!
的值存储在 constexpr int
中确实 yields a nice compile error:
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) 的调用?..)
然后,我从 x
中删除 constexpr
,但将 f
设为 consteval
。根据 the docs:
consteval - specifies that a function is an immediate function, that is, every call to the function must produce a compile-time constant
我预计这样的程序会再次导致编译错误。但是,the program compiles and runs with UB.
这是为什么?
UPD: 评论者认为这是一个编译器错误。我举报了:https://bugs.llvm.org/show_bug.cgi?id=43714
这是一个编译器错误。或者,更准确地说,这是一个“未充分实现”的功能(参见 the comment in bugzilla):
Yup - seems consteval isn't implemented yet, according to: https://clang.llvm.org/cxx_status.html
(the keyword's probably been added but not the actual implementation support)