template<integral auto n1, decltype(n1) n2, class callable_t, class... args_t> requires (n1 <= n2)
constexpr void const_for(callable_t&& callable, args_t&&... args)
{
callable<n1>(forward<args_t>(args)...);
if constexpr (n1 < n2) { callable<n1 + 1>(forward<args_t>(args)...); }
}
I can't understand what is the problem here. But in visual studio 2022, it gives the following errors (line 4 and 6):
Error C2760 syntax error: '...' was unexpected here; expected ')'
Error C2760 syntax error: ')' was unexpected here; expected ';'
Error C3878 syntax error: unexpected token ')' following 'expression_statement'
etc.
Lemme reduce to just one argument to make this clearer:
callable<n1>(arg);
What this means, given an object (i.e., not a function template, not a variable template, but an actual object) is:
(callable < n1) > (arg)
That is, the <
is parsed as the less-than operator, not as an introducer for template arguments. This is one of the issues with using <>
s for both contexts (and why the D language, for instance, uses !
- which is one of those syntactic choices that seems incredibly jarring when you first see it but is definitely a good idea).
In some contexts, you can use the template
keyword to disambiguate that no, you do actually mean to introduce template arguments. You'd see something like:
using A = typename B::template C<D>;
But here, that's not an option - because, again, callable
is an object, and objects can't take template arguments.
The solutions here are:
callable.operator()<n1>(arg)
callable(integral_constant<decltype(n1), n1>(), arg)
The latter has a lot going for it and is a pretty nice pattern, so I would recommend doing that. It becomes nicer with an alias:
template <auto V>
using constant = std::integral_constant<decltype(V), V>;
Because then callable(constant<n1>(), arg)
.