Reputation: 23042
Suppose I have a meta-function which requires both the type and its arguments. How can I do this without forcing the user of the function to provide both the type and its arguments separately?
using MyType = SomeType<T1, T2, T3>; // This is the type to pass to the functor
template <typename MyType, typename ... Args>
struct MetaFunction
{
using type = SomeOperation<MyType, Args...>;
}
// I want to be able to call my functor like this:
MetaFunction<MyType>::type;
// but with the above I have to call it like this:
MetaFunction<MyType, T1, T2, T3>::type;
How can I do this?
Upvotes: 4
Views: 263
Reputation: 39101
You can "disassemble" a class template specialization into the template itself and the template parameters by using partial spezialiation (some form of pattern-matching).
First, we define MetaFunction
to be a (class) template that takes a type as its only parameter:
template <typename T>
struct MetaFunction;
Then, we define a partial specialization of this class template MetaFunction
. A partial specialization is a special case of a class template. If the case applies, the partial specialization is used instead of the original (primary) template to make a class. The template "interface", i.e. the amount and kind of template arguments you can/must provide to instantiate the MetaFunction
template is not changed by the existence of specializations.
A partial specialization, as opposed to an explicit specialization, is also a template, which implies that it has template parameters. The partial means that it does not specify fully for which types (sets of template arguments) it applies as a special case. Typically, partial specializations apply to subsets of the set of possible/valid arguments you can supply to the primary template.
template <template<typename...> class TT, typename ... Args>
struct MetaFunction /* not finished yet */
There are three kinds of template parameters:
This partial specialization uses a template template-parameter. A valid argument for such a parameter must be a either a class template or an alias template.
We specify when this partial specialization shall be used by providing a "pattern":
template <template<typename...> class TT, typename ... Args>
struct MetaFunction<TT<Args...>>
{
using type = SomeOperation<TT, Args...>;
};
This partial specialization will be used if the type supplied to the MetaFunction
template matches the pattern TT<Args...>
, i.e., if it can be disassembled into a class/alias(*) template TT
and some template type parameters Args
.
(*) As T.C. correctly noted, a type produced via an alias-template is not associated with the alias-template. Therefore, you cannot deduce an alias-template from a type.
Upvotes: 4