c++ - 何时在 constexpr 函数中使用模板非类型类或普通参数

标签 c++ constexpr c++20 constant-expression

我非常不清楚何时在 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/

相关文章:

c++ - 在 STL make_heap c++​​ 中将函数指针作为比较器传递

c++ - 错误 : request for member which is of non class type

c++ - span 可以是 constexpr 吗?

c++ - 为什么这不是一个常量表达式?

python - 使用 conda 安装 glpk cvxopt

c++ - 将 gdb 显示保存到变量

c++ - C++ 中的 "poison a function"是什么意思?

c++ - 闰秒和 std::chrono

c++ - 为什么 C++ 20 范围算法位于 <algorithm> 中, View 位于 <ranges> 中?

C++20 协程使用 Final_suspend 进行延续