38

テンプレート エイリアスをテンプレート テンプレート パラメータとして使用できますか?

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?
4

2 に答える 2

26

はい、許可されているようです。私が見つけた次の標準の最新のドラフトによると、次のように述べられています

テンプレートtemplate-parameterのテンプレート引数は、クラス テンプレートまたはエイリアス テンプレートの名前にする必要があります [...]。

ただし、エイリアス テンプレートは現時点ではほとんどサポートされていないように思われるため、ほとんどのコンパイラで動作させるのに問題が生じる可能性があります。

于 2011-09-06T12:35:55.370 に答える
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 スタイルのメタ関数 (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をパラメーター packに適用するメタ関数を作成できます。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) メタ関数の違いを抽象化します。

于 2013-07-18T13:36:54.383 に答える