尝试实现is_constexpr()-编译器不同

Cas*_*eri 6 c++ language-lawyer constexpr c++17

以下是三次尝试实现is_constexpr()根据理查德·史密斯回答是is_constexpr可能在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); }
Run Code Online (Sandbox Code Playgroud)

版本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); }
Run Code Online (Sandbox Code Playgroud)

版本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); }
Run Code Online (Sandbox Code Playgroud)

我已经使用gcc 9.1,clang 8.0.0,icc 19.0.1和msvc 19.20以及以下功能的帮助测试了以上内容(请参见godbolt):

void constexpr f_c(int) {}
void f_nc(int) {}
Run Code Online (Sandbox Code Playgroud)

下表显示了我放在中的表达式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 |
Run Code Online (Sandbox Code Playgroud)

谁是正确的,为什么?(标准中的引用将很有用。)

Bar*_*rry 8

无论是is_constexpr_1也不is_constexpr_2是有效的,因为它们运行触犯通常的规则是函数的参数不是常量表达式使用。它们分别要求xf至少有时可以用作常量表达式,而它们从来都不是。

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

引用引用类型的变量或数据成员的id表达式,除非引用具有前面的初始化且[...]

没关系,其他两个项目符号是什么,因为我们在引用变量的id表达式中没有预先进行的初始化。

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
Run Code Online (Sandbox Code Playgroud)

这是c所做的。