Могу ли я использовать псевдонимы шаблона в качестве параметров шаблона? - PullRequest
35 голосов
/ 06 сентября 2011

Можно ли использовать псевдонимы шаблона в качестве параметров шаблона?

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 ]

25 голосов
/ 06 сентября 2011

Да, это, по-видимому, разрешено.Согласно последнему проекту следующего стандарта, который я смог найти, указано, что

A аргумент шаблона для шаблона параметр-шаблона должен бытьимя шаблона класса или шаблона псевдонима [...].

Однако шаблоны псевдонимов в настоящее время поддерживаются очень редко, поэтому у вас могут возникнуть проблемы сэто работает с большинством компиляторов.

1 голос
/ 18 июля 2013

Люди, которые читают исходный вопрос, могут писать структуры, которые используют параметры шаблона шаблона как мета-функции , как показано в листинге ниже.

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 и add_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 для пакета параметров 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) метафункциями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...