我有一个使用“经典”SFINAE 的代码。
template<class M> auto power(M const& elem) -> decltype(std::norm(elem)) { return std::norm(elem); }
template<class M, class = std::enable_if_t<(M::rank::value >= 1)>>
auto power(M const& array) {
return accumulate(begin(array), end(array), 0.0, [](auto const& alpha, auto const& omega) { return alpha + power(omega); });
}
这是一个递归(跨维度或等级)“幂”函数,通过计算较低维度的子元素的幂,最终给出元素的平方和。
现代 C++ 鼓励使用if constexpr
以避免使用 SFINAE,如下所示。
template<class M>
auto power(M const& array) {
if constexpr(M::rank::value >= 1) {
return accumulate(begin(array), end(array), 0.0, [](auto const& alpha, auto const& omega) { return alpha + power(omega); });
} else {
return std::norm(array);
}
}
问题在于, 中的表达式似乎if constexpr
首先必须是有效的表达式。元素没有名为 的成员类型rank
,因此存在编译错误。
if constexpr
如果表达式无效,是否有一个技巧可以使谓词成立?
C++20 及更新版本:
还有一个不太详细的选项:
但后者更糟糕,因为如果编译时不知道条件,它会导致硬错误,而前者只是返回 false。
前者在标准库中使用(另请参见在嵌套需求中,为什么使用
requires bool_constant<X>::value;
而不是requires X;
?)。C++17:
使用检测惯用法:
然后: