3 votes

Spécifier un modèle par défaut

Considérez ceci :

template <typename Pack, template <typename...> class = std::tuple> struct foo;

template <template <typename...> class P, typename... Ts, template <typename...> class Q>
struct foo<P<Ts...>, Q> {
    using type = Q<P<Ts>...>;   
};

J'ai placé le modèle par défaut dans le typedef pour être std::tuple pour que ça compile, mais ce que je veux en fait, c'est que le modèle par défaut soit P et je ne connais pas de syntaxe qui le permette. J'ai gardé le typedef simple pour illustrer le point, qui est d'essayer d'avoir P comme modèle par défaut. J'ai donc trouvé la solution suivante, qui semble assez moche :

template <typename Pack, template <typename...> class...> struct foo;

template <template <typename...> class P, typename... Ts, template <typename...> class Q>
struct foo<P<Ts...>, Q> {
    using type = Q<P<Ts>...>;   
};

template <template <typename...> class P, typename... Ts>
struct foo<P<Ts...>> {
    using type = P<P<Ts>...>;   
};

Y a-t-il une meilleure façon de procéder que celle-ci ? Peut-être une syntaxe c++17 que je ne connais pas ?

2voto

max66 Points 4276

Dans ce cas, using (combiné avec template ) est votre ami.

Vous avez besoin d'un type-traits pour extraire le conteneur en Pack par exemple

template <typename>
struct bar;

template <template <typename...> class P, typename ... Ts>
struct bar<P<Ts...>>
 {
   template <typename ... Us>
   using templ_type = P<Us...>;
 };

afin de pouvoir extraire la valeur par défaut, pour le deuxième paramètre du modèle, de Pack comme suit

template <typename Pack,
          template <typename...> class = bar<Pack>::template templ_type>
struct foo;

Voici un exemple de compilation complète

#include <type_traits>

template <typename ...>
struct baz
 { };

template <typename>
struct bar;

template <template <typename...> class P, typename ... Ts>
struct bar<P<Ts...>>
 {
   template <typename ... Us>
   using templ_type = P<Us...>;
 };

template <typename Pack,
          template <typename...> class = bar<Pack>::template templ_type>
struct foo;

template <template <typename...> class P, typename... Ts,
          template <typename...> class Q>
struct foo<P<Ts...>, Q>
 { using type = Q<P<Ts>...>; };

int main()
 {
   foo<baz<short, int, long>>  f0;

   static_assert( std::is_same<decltype(f0)::type,
      baz<baz<short>, baz<int>, baz<long>>>{}, "!" );
 }

1voto

Barry Points 45207

Si vous recherchez un défaut différent qui soit une identité, vous pouvez créer une telle chose :

template <class... I> struct foo_id_impl;
template <template <class...> class P, class... Ts>
struct foo_id_impl<P<Ts>...> { using type = P<P<Ts>...>; };

template <class... Id>
using foo_id = typename foo_id_impl<Id...>::type;

template <class Pack, template <class...> class = foo_id>
struct foo;

Je ne suis pas sûr que ce soit nécessairement mieux que votre solution, mais peut-être que si vous en avez besoin à plusieurs endroits

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