我可以使用模板别名作为模板模板参数吗?

时间:2011-09-06 12:00:51

标签: c++ templates c++11 template-aliases

我可以使用模板别名作为模板模板参数吗?

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?

2 个答案:

答案 0 :(得分:25)

是的,显然是允许的。根据我能找到的即将出台的标准的最新草案,据说

  

模板的 template-argument template-parameter 应为类模板或别名模板的名称[...]。

但是,别名模板seems very seldomly supported目前,因此您可能会遇到一些问题,因为它可以与大多数编译器一起使用。

答案 1 :(得分:1)

阅读原始问题的人可能正在编写使用模板模板参数作为元函数的结构,如下面的清单所示。

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_1add_2都是元功能,让我们区分

  • add_1作为嵌套typedef-style 元函数的示例(支持c ++ 03)
  • add_2作为模板别名样式元函数的示例(需要c ++ 11)

binary_op结构可以使用模板别名样式嵌套的typedef样式元函数,但不能同时使用两者。在这个答案中,我展示了如何重写这样的TMP代码以避免这个问题。

假设您希望将模板模板参数Function应用于值Ts...的参数包。要应用元函数,您需要

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

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

使用另一个通用元函数来检测传递的元函数的类型并相应地应用它将是有用的。

下面实现的is_alias_metafunction函数是这种设施的构建块:

#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;
};

现在,我们可以编写一个元函数apply,将模板模板参数Function应用于参数包Ts...,无论Function是模板别名还是模板结构。

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;

我们现在可以使用apply元函数,如下所示:

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

它将抽象出'遗留'元函数和现代(c ++ 11)元函数之间的差异。