尝试实现IS_CONSTEXPR() - 编译器差异
Attempt to implement is_constexpr() - compilers diverge
以下是基于理查德·史密斯(Richard Smith(对IS_Constexpr的答案在C 11中实现is_constexpr()
的三次尝试?
版本1
template <typename T>
bool constexpr is_constexpr_impl_1(const T& x, decltype(int{(x, 0u)})) { return true; }
template <typename T>
bool constexpr is_constexpr_impl_1(const T&, ...) { return false; }
template <typename T>
bool constexpr is_constexpr_1(const T& x) { return is_constexpr_impl_1(x, 0); }
版本2
template <typename T>
bool constexpr is_constexpr_impl_2(const T& f, decltype(int{(f(0), 0u)})) { return true; }
template <typename T>
bool constexpr is_constexpr_impl_2(const T&, ...) { return false; }
template <typename T>
bool constexpr is_constexpr_2(const T& f) { return is_constexpr_impl_2(f, 0); }
版本3
template <auto f>
bool constexpr is_constexpr_impl_3(decltype(int{(f(0), 0u)})) { return true; }
template <auto f>
bool constexpr is_constexpr_impl_3(...) { return false; }
template <auto f>
bool constexpr is_constexpr_3() { return is_constexpr_impl_3<f>(0); }
我已经用GCC 9.1,Clang 8.0.0,ICC 19.0.1和MSVC 19.20测试了以上(请参阅Godbolt(,以及以下功能的帮助:
void constexpr f_c(int) {}
void f_nc(int) {}
下表显示了我在static_assert
中放置的表达式。我希望所有人都通过,但编译器不同意我和之间的意见(ICC和MSVC彼此一致(:
| gcc | clang | icc | msvc |
is_constexpr_1(0) | pass | fail | pass | pass |
is_constexpr_2(f_c) | fail | fail | pass | pass |
!is_constexpr_2(f_nc) | pass | pass | fail | fail |
is_constexpr_3<f_c>() | pass | pass | pass | pass |
!is_constexpr_3<f_nc>() | pass | pass | fail | fail |
谁是对的,为什么?(标准的报价将很有用。(
is_constexpr_1
和is_constexpr_2
都不是有效的,因为它们符合通常的规则,即功能参数在常数表达式中不可用。它们分别需要x
和f
至少有时可作为恒定表达式使用,而它们从来没有。
在这种情况下,[expr.const]/4的限制:
AN id-expression 是指参考类型的变量或数据成员
其他两个子弹是什么都没有关系,因为我们在 id-expression 上没有提到变量的初始化。
is_constexpr_3
是有效的,正如理查德·史密斯(Richard Smith(在链接的答案中解释的那样。
我的期望是:
|
is_constexpr_1(0) | fail
is_constexpr_2(f_c) | fail
!is_constexpr_2(f_nc) | pass
is_constexpr_3<f_c>() | pass
!is_constexpr_3<f_nc>() | pass
Clang的作用。
相关文章:
- 编译器生成的默认构造函数具有 constexpr 混淆行为
- 如果在 lambda 中使用 Constexpr static_assert,哪个编译器是正确的?
- G++ 编译器是否在未使用返回值的情况下将 constexpr 函数视为常规函数?
- 编译器如何知道C++constexpr计算不会触发未定义的行为
- 没有编译器支持Constexpr Memcpy的bit_cast可能吗?
- 为什么编译器无法弄清楚构造函数实际上是 constexpr?
- 静态 constexpr 的编译器优化
- 如何让编译器忽略这个计算结果为 false 的 if-constexpr?
- 如果 Constexpr 在 lambda 中,则编译器行为不同
- 如果递归通用 lambda 中的 constexpr:不同的编译器行为
- "如果 constexpr",在 lambda 内部,在包扩展内部 - 编译器错误?
- 表达式未评估为常数两个级别的constexpr函数(编译器错误?)
- 使用constexpr c-string作为编译器错误消息
- 为什么我的编译器显示有关我的 constexpr 函数的此错误?
- 跨编译器的 constexpr 成员函数的重载解析不一致
- 如何使我的C 编译器发出constexpr值(例如警告?)
- 将默认赋值运算符声明为 constexpr:哪个编译器是正确的?
- 引用基类的 constexpr 构造函数因编译器而异
- 从编译器优化和代码性能的角度来看,"if constexpr"与"if"
- 编译器之间在丢弃的 if constexpr(false) 语句中实例化模板的行为不一致