c++ - 尝试实现 is_constexpr() - 编译器分歧

标签 c++ language-lawyer c++17 constexpr

以下是基于 Richard Smith 实现 is_constexpr() 的三种尝试的 answerIs is_constexpr possible in C++11?

版本 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_1is_constexpr_2 都无效,因为它们违反了常量表达式中不能使用函数参数的通常规则。它们分别要求 xf 至少有时可用作常量表达式,但它们永远不会。

在这种情况下,[expr.const]/4限制:

an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization and either [...]

其他两个项目符号是什么无关紧要,因为我们没有对引用变量的 id-expression 进行预先初始化。

is_constexpr_3 是有效的,正如 Richard Smith 在 linked answer 中解释的那样.

我的期望是:

                        | 
 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 所做的。

关于c++ - 尝试实现 is_constexpr() - 编译器分歧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56243158/

相关文章:

c++ - 在 C++ 中将 Int 数据保存到文本文件中

c++ - 如何将模式从 Dev-C++ 中的 c++98 模式更改为支持 C++0x 的模式(基于范围)?

可以作为 "double (*)[4]"传递的 c++11 对象

c - 对于浮点宏,C 标准的 "converted to its semantic type"是什么意思?

c++ - 如何在 string_view 中推断出悬空指针?

c++ - unique_ptr 的有状态自定义删除器

c++ - 用 vector 的 vector 的元素初始化 vector 的空 vector

c++ - 将类型为 `int` 的临时对象转换为引用安全吗?

c++ - 严格别名规则是否适用于函数调用?

c++ - 在堆栈上分配对齐的内存,如 _alloca