Question

Can I use template aliases as template template parameters?

template <template <typename...> class> struct foo {};

template <typename T> using simple_ptr = std::unique_ptr<T>;

foo<std::unique_ptr> a; // this doesn't work, std::unique_ptr has two parameters
foo<simple_ptr> b; // does this work?
Was it helpful?

Solution

Yes, it is apparently allowed. According to the latest draft of the upcoming standard I could find, it is stated that

A template-argument for a template template-parameter shall be the name of a class template or an alias template [...].

However, alias templates seems very seldomly supported at the moment, so you might have some trouble making it work with most compilers.

OTHER TIPS

People who read the original question may be writing structs that use template template parameters as meta functions, as demonstrated in the listing below.

template <int T>
struct integer
{
        using value = T;
};

template <class T, class U, template <class...> class Function>
struct binary_op
{
        // Works for add_1, but not add_2
        using type = typename Function<T, U>::type;

        // Works for add_2, but not add_1
        using type = Function<T, U>;
};

template <class T, class U>
struct add_1;

template <int T, int U>
struct add_1<integer<T>, integer<U>>
{
        using type = integer<T + U>;
};

template <class T, class U>
using add_2 = typename add_1<T, U>::type;

add_1 and add_2 are both meta-functions, let's distinguish

  • add_1 as an example of nested typedef-style metafunction (which c++03 supported)
  • add_2 as an example of template alias-style metafunction (which requires c++11)

The binary_op struct can work either with template alias-style or nested typedef-style metafunctions, but not both. In this answer, I show how such TMP code can be rewritten to avoid this problem.

Suppose that you wish to apply a template template parameter Function to a parameter pack of values Ts.... To apply the metafunction, you need either

using type = Function<Ts...>; // template-alias style

or

using type = typename Function<Ts...>::type; // nested typedef style

It would be useful to have another generic metafunction that detects the kind of metafunction that was passed, and applys it accordingly.

The is_alias_metafunction function, which is implemented below, is a building block for such a facility:

#include <type_traits>

template <class... Ts>
struct sequence;

template <class T>
struct check
{
    static constexpr bool value = true;
};

template <
    template <class...> class Function,
    class                     S,
    class                     Check = void
>
struct is_alias_metafunction
{
    static constexpr bool value = true;
};

template <
    template <class...> class Function,
    class...                  Ts
>
struct is_alias_metafunction<
    Function,
    sequence<Ts...>,
    typename std::enable_if<
        check<typename Function<Ts...>::type>::value
    >::type
>
{
    static constexpr bool value = false;
};

Now, we can write a metafunction apply that applies a template template parameter Function to the parameter pack Ts..., regardless of whether Function is a template alias or a template struct.

template <
    bool                      IsAlias,
    template <class...> class Function,
    class                     S
>
struct apply_impl;

template <template <class...> class Function, class... Ts>
struct apply_impl<true, Function, sequence<Ts...>>
{
    using type = Function<Ts...>;
};

template <template <class...> class Function, class... Ts>
struct apply_impl<false, Function, sequence<Ts...>>
{
    using type = typename Function<Ts...>::type;
};

template <template <class...> class Function, class... Ts>
using apply = typename apply_impl<
    is_alias_metafunction<Function, sequence<Ts...>>::value,
    Function,
    sequence<Ts...>
>::type;

We can now use the apply metafunction as follows:

using type = apply<Function, Ts...>;

and it will abstract away the difference between 'legacy' metafunctions and modern (c++11) metafunctions.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top