This is more of a conceptual question. I\'m trying to find the easiest way of converting a two-arg template (the arguments being types) into a one-arg template. I.e., binding on
I think the typical way of doing this is keep everything in the world of types. Don't take template templates - they're messy. Let's write a metafunction named ApplyAnInt
that will take a "metafunction class" and apply int
to it:
template
struct ApplyAnInt {
using type = typename Func::template apply;
};
Where a simple metafunction class might be just checking if the given type is an int
:
struct IsInt {
template
using apply = std::is_same;
};
static_assert(ApplyAnInt::type::value, "");
Now the goal is to support:
static_assert(ApplyAnInt>::type::value, "");
We can do that. We're going to call types that contain _
"lambda expressions", and write a metafunction called lambda
which will either forward a metafunction class that isn't a lambda expression, or produce a new metafunction if it is:
template
struct lambda {
using type = T;
};
template
struct lambda::value>>
{
struct type {
template
using apply = typename apply_lambda::type;
};
};
template
using lambda_t = typename lambda::type;
So we update our original metafunction:
template
struct ApplyAnInt
{
using type = typename lambda_t::template apply;
};
Now that leaves two things: we need is_lambda_expr
and apply_lambda
. Those actually aren't so bad at all. For the former, we'll see if it's an instantiation of a class template in which one of the types is _
:
template
struct is_lambda_expr : std::false_type { };
template class C, typename... Ts>
struct is_lambda_expr> : contains_type<_, Ts...> { };
And for apply_lambda
, we just will substitute the _
with the given type:
template
struct apply_lambda;
template class C, typename... Ts, typename U>
struct apply_lambda, U> {
using type = typename C::value, U, Ts>...>::type;
};
And that's all you need actually. I'll leave extending this out to support arg_
as an exercise to the reader.