我非常不清楚何时在 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
,那就出乎意料了。函数在编译时有效,但在运行时不再有效。
人们可以期待新的 consteval
C++20 中的关键字,可以使用 consteval
的普通参数常量表达式中的函数,因为我们知道这些参数必须是常量表达式。但情况似乎并非如此:https://godbolt.org/z/guz7FQ我不知道为什么会这样。但总的来说,我喜欢普通变量和非类型模板参数之间的分离。
关于c++ - 何时在 constexpr 函数中使用模板非类型类或普通参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59586999/