我不清楚何时在constexpr函数中使用非类型模板参数(C ++ 20)或普通参数。对我来说,尚不清楚限制是什么,何时从纯参数切换到non-type template parameters
(请参阅Live)。这是一个使用普通参数:
template<typename Tuple, typename Pred>
constexpr auto getLambda(Tuple&& tuple, Pred&& pred)
{
return [=](auto I, auto J) {
return pred(std::get<I>(tuple), std::get<J>(tuple));
};
}
template<typename T>
struct A
{
constexpr A(T t) : val(t){};
T val;
};
int main()
{
static constexpr auto t = std::make_tuple(A{10.0}, A{1});
constexpr auto p = [](auto&& a, auto&& b) { return a.val < b.val; };
constexpr auto s = getLambda(t, p);
//constexpr auto b = s(1,0); // that does unfortunately not compile -> go back write differently... :-|||
}
[通常,我首先尝试使用如上所述的普通参数,并在麻烦解决non-constant
表达式的编译错误之后,尝试使用template<auto t>
(非类型模板参数。通常每个方法都有两个实现,情况(对我来说这似乎很愚蠢...)
在我看来,使用C ++ 20的现代泛型编程倾向于使用constexpr
和一些类型元编程来进行编译时计算。任何人都可以对这种相当新的C ++“黑暗角落”有所了解。我可能误会了什么时候不是constant-expression
,什么时候...
简短版本:使用非类型模板参数设置非类型模板参数(在任何地方都需要constant expression时更通用)以及其他所有参数的常规参数。
关于constexpr
函数的所有注意事项是,它们也可以在运行时调用。因此,每个常规参数都不一定是常量表达式。因此,您不能使用它来提供非类型的模板参数(如I
中的std::get<I>
)。
当然,可以辩称,当调用它来计算constexpr
变量时,传递的参数始终是常量表达式,因此也可以在函数内部使用。但是,如果constexpr
函数在编译时起作用但在运行时不再起作用,这将是意外的。
人们可以期望,在C ++ 20中使用新的consteval
关键字,就可以在常量表达式中对consteval
函数使用常规参数,因为我们知道这些参数必须是常量表达式。但这似乎并非如此:consteval
为什么我不知道这种情况。但总的来说,我喜欢普通变量和非类型模板参数之间的分隔。