我有以下代码:
#include <string_view>
#include <iostream>
#include <cstring>
consteval const char* compile_time_trim(const std::string_view& s) noexcept{
return s.data() + s.find("/app/") + strlen("/app/");
}
constexpr const char* best_effort_trim(const std::string_view& s) noexcept{
if consteval {
return compile_time_trim(s);
}
else {
return s.data();
}
}
int main() {
std::cout << best_effort_trim(__FILE__) << std::endl;
}
GCC 14.1 发出错误:
<source>: In function 'int main()':
<source>:19:34: in 'constexpr' expansion of 'best_effort_trim(std::basic_string_view<char>(((const char*)"<source>")))'
<source>:11:33: error: call to consteval function 'compile_time_trim((* & s))' is not a constant expression
11 | return compile_time_trim(s);
| ~~~~~~~~~~~~~~~~~^~~
In file included from <source>:1:
<source>:19:34: in 'constexpr' expansion of 'best_effort_trim(std::basic_string_view<char>(((const char*)"<source>")))'
<source>:11:33: in 'constexpr' expansion of 'compile_time_trim((* & s))'
<source>:6:18: in 'constexpr' expansion of '(& s)->std::basic_string_view<char>::data()'
/opt/compiler-explorer/gcc-14.1.0/include/c++/14.1.0/string_view:290:22: error: '*(const std::basic_string_view<char>*)this' is not a constant expression
290 | { return this->_M_str; }
| ~~~~~~^~~~~~
Compiler returned: 1
但是,如果我将
constexpr const char* best_effort_trim(
更改为consteval const char* best_effort_trim(
,GCC就没有错误。
虽然宏
__FILE__
是一个编译时常量,但似乎如果将其传递给constexpr
函数,s
将被视为非常量(即使它可以在编译时构造)但为什么呢?
但是如果
s
被认为是非常量表达式,我认为 return compile_time_trim(s);
甚至不会被评估。 但错误表明情况并非如此。 为什么?
谁能详细解释一下这是怎么回事?
谢谢!
这是一个已确认的 GCC 错误。
return compile_time_trim(s);
不应在您的示例中执行。
GCC 是错误的,因为
if consteval
块在不应该执行的时候被执行了。
[stmt.if] p5 指出:
该术语定义如下:
表达式或转换是
明显常量评估,如果它是:
a常量表达式
在语句- ,或 constexpr if 语句的条件 ([stmt.if]),或
- 立即调用,或者
- 将结果代入原子约束表达式以确定是否满足([temp.constr.atomic]),或者
- 可在常量表达式中使用或具有常量初始化的变量的初始值设定项([basic.start.static])。
std::cout << best_effort_trim(__FILE__) << std::endl;
中,这些条件都不成立,因此不会进行持续评估。 该错误似乎与 GCC 在启用优化时错误地进行持续评估有关;该标准不允许这样任意的持续评估。
当您将best_effort_trim
更改为
consteval
时,该调用是立即调用,并且会按其应有的方式不断进行评估。