Questions regarding the use of C++14 generic lambdas or C++20 template lambdas are typically about generating lambdas with the appropriate parameterized types.
My question is, is it possible for a lambda parameter, or its evaluation, to force the instantiation (or specialization) of a template, e.g., a template function? The parameter (n)
would need to be qualified as constexpr
for this to work.
template <int n> ret_type fn (...) {...}
...
auto fx = [] (int n) { return fn<n>(...) }
I'm not completely up to date with C++20, or newer working proposals, and admit there are still nuances with constexpr
, etc., in C++17 lambdas and other edge features, that have me looking up cppreference
, Josuttis, and others pretty frequently.
I know this close to an XY-problem. Since template instantiation is performed at compile time, a lambda expression for a template parameter seems like an anti-pattern. But since templates can be instantiated if types and constant values are known at compile time, are there any proposals to allow such a mechanism?
The answer to your question is technically yes, lambda bodies can instantiate template functions. The actual example doesn't work, because int n
as a parameter can't be used that way.
There is an easy workaround
template<auto x>
using constant_t = std::integral_constant< std::decay_t<decltype(x)>, x >;
template<auto x>
constexpr constant_t<x> constant = {};
template <int n> int fn () { int arr[n] = {0}; return sizeof(arr); }
auto fx = [] (auto n) { return fn<n>(); };
std::cout << fx( constant<3> );
Here I made the constant<x>
variable template that creates an instance of std::integral_constant<X, x>
. This is a stateless (but not valueless!) type that has a constexpr conversion to its value.
We can pass that to a lambda, and so long as the lambda takes it by value we can then convert it to a constexpr
value within the lambda, including passing it as a template non-type parameter, instantiating a template function specialization as you are asking for.
The can be done without the constant
variable template, ie if you don't have auto
parameter support:
template<std::size_t N>
using index_t = std::integral_constant<std::size_t, N>;
template<std::size_t N>
constexpr index_t<N> index = {};
we can use a type-specific version of it, and just pass that, and it works the same way.
Aside, constant<?>
is fun. For example:
using upFILE=std::unique_ptr<
std::FILE,
constant_t<std::fclose>
>;
upFILE file( fopen("hello.txt", "r") );
does the right thingtm.