I am very unclear when to use non-type template arguments (C++20) or normal arguments in constexpr functions. It's unclear to me, what the restrictions are and when to switch from pure parameters to non-type template parameters
(see Live).
Here an example which illustrates the clunkiness with normal arguments:
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... :-|||
}
Mostly I first try to use normal arguments like above, and after cumbersome fiddling with compile errors about non-constant
expressions, try an approach with template<auto t>
(non-type template paramters. Mostly having then two implementations one for each use-case (this seems stupid to me...)
Its sounds to me that modern generic programming with C++20 tends towards compile-time computations using constexpr
together with some type-meta-programming.
Could anyone shed some light into this rather new "dark-corner" of C++. I probably misunderstand
when something is not a constant-expression
and when it is...