nic*_*lai 10 c++ constant-expression c++17
请参考以下代码段:
#include <type_traits>
#include <string_view>
constexpr std::size_t strlen(char const* s) {
std::size_t n = 0;
while (*s++ != '\0')
++n;
return n;
}
template <std::size_t>
struct X {};
int main() {
constexpr auto pf = __PRETTY_FUNCTION__; // gcc ok; clang ok; (1)
static_assert(std::string_view(__PRETTY_FUNCTION__) == std::string_view("int main()")); // gcc ok; clang ok; (2)
X<strlen(__PRETTY_FUNCTION__)> x; // gcc not ok; clang ok; (3)
}
Run Code Online (Sandbox Code Playgroud)
Clang 8编译它,但GCC 8.3不会编译。查看godbolt。GCC的线路出现故障(3),虽然线(1)和(2)都OK。如果我能够pf在行中声明(1)并使用它__PRETTY_FUNCTION__,static_assert则表示该表达式__PRETTY_FUNCTION__是核心常量表达式。如果我无法声明,X<strlen(__PRETTY_FUNCTION__)> x则表示它strlen(__PRETTY_FUNCTION__)不是整数常量表达式。
那么为什么strlen(__PRETTY_FUNCTION__)不是整数常量表达式呢?是标准隐含的,还是GCC错误?
__PRETTY_FUNCTION__不是标准的。这样,编译器可以在不同的地方(在解析,构建AST或链接时)实现它。
如果应该在解析时实现它,那么它可以是一个常量表达式(我想这就是clang所做的事情)。但是,如果它是在链接时实现的(也就是说,编译器会为其发出符号,并且链接器将解析它),则它不能是常量表达式。
我认为海湾合作委员会使用后一种情况。
请注意,在这种情况下,您可以使用这些参数的sizeof(),因为这是const char[]需要编译时常量字符串长度计算的条件。因此,将表达式3替换为:
X<sizeof(__PRETTY_FUNCTION__) - 1> x;
Run Code Online (Sandbox Code Playgroud)
并且可以在两个编译器上正常编译。
编辑:正如NathanOliver指出的那样,似乎GCC认为__PRETTY_FUNCTION__as 的签名,static const char[]而clang / visual studio则认为as 的签名static constexpr const char[]。这在GCC中是一个令人讨厌的麻烦(不是错误,因为它不是标准的),并且他们似乎已在> 8.0.0版本中对其进行了修复。
在表达式(1)和表达式(2)中,__PRETTY_FUNCTION__衰减为a const char*(指针是常数,但是关于数据什么也不能说)。对我来说,表达式(2)不能证明任何事情,因为不能保证指针在相等的两边都应该相等,即使它们指向“相同”的内容也是如此。string_view构造函数期望const char*,因此除此以外的任何东西都__PRETTY_FUNCTION__可以衰减以const char*传递表达式(2)。
| 归档时间: |
|
| 查看次数: |
505 次 |
| 最近记录: |