quant
quant

Reputation: 23042

How can I deduce the type and its template arguments for a meta-function?

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

Answers (1)

dyp
dyp

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:

  • Type parameters
  • "Value" parameters (non-type)
  • 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

Related Questions