37 votes

Puis-je utiliser des alias de modèle comme paramètres de modèle de modèle?

Puis-je utiliser des alias de modèle comme paramètres de modèle de modèle?

 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?
 

25voto

Luc Touraille Points 29252

Oui, c'est apparemment autorisé. Selon la plus récente version de la norme à venir que j'ai pu trouver, il est indiqué que

Un modèle d'argument pour un modèle un modèle paramètre est le nom d'un modèle de classe ou un alias de modèle [...].

Cependant, alias modèles semble très rarement pris en charge à l'heure actuelle, de sorte que vous pourriez avoir quelques difficultés à le faire fonctionner avec la plupart des compilateurs.

1voto

void-pointer Points 2720

Les personnes qui lisent la question d'origine peut être écrit les structures qui utilisent le modèle de paramètres de modèle en tant que méta-fonctions, comme le montre la liste ci-dessous.

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 et add_2 sont à la fois méta-fonctions, nous allons distinguer

  • add_1 comme un exemple de imbriquée typedef style metafunction (qui c++03 pris en charge)
  • add_2 comme un exemple de modèle d'alias de style metafunction (ce qui nécessite de c++11)

L' binary_op struct peut fonctionner soit avec le modèle alias de style ou imbriqués typedef style metafunctions, mais pas les deux. Dans cette réponse, je montre comment ces TMP code peut être réécrit afin d'éviter ce problème.

Supposons que vous souhaitez appliquer un modèle paramètre de modèle Function à un paramètre pack de valeurs Ts.... Pour appliquer le metafunction, vous avez besoin de

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

ou

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

Il serait utile d'avoir un autre générique metafunction qui détecte le type de metafunction qui a été passé, et applys en conséquence.

L' is_alias_metafunction de la fonction, qui est mis en œuvre ci-dessous, est un bloc de construction pour une installation de ce type:

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

Maintenant, nous pouvons écrire une metafunction apply qui s'applique un modèle de paramètre de modèle Function pour le paramètre pack Ts..., indépendamment de si Function est un modèle d'alias ou d'un modèle de structure.

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;

Nous pouvons maintenant utiliser l' apply metafunction comme suit:

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

et il va abstraire la différence entre "héritage" metafunctions et moderne du c++(c ++ 11) metafunctions.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X