IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Expansion de parameter pack appliquée aux integer_sequence


Sujet :

Langage C++

  1. #1
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut Expansion de parameter pack appliquée aux integer_sequence
    En cherchant comment générer une séquence de nombres entiers à partir de paramètres template selon des règles définies par moi-même, je suis tombé sur cette réponse de Jarod42 sur SO qui me dépasse un peu.

    Je me suis permis de reproduire son exemple ci-dessous, traduit en C++17 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include <type_traits>
    #include <utility>
     
    namespace detail
    {
        template <typename Seq1, std::size_t Offset, typename Seq2> struct concat_seq;
     
        template         <std::size_t            ...Is1, std::size_t Offset, std::size_t            ...Is2>
        struct concat_seq<std::index_sequence<Is1...>  ,             Offset, std::index_sequence<Is2...>  >
        {
            using type = std::index_sequence<Is1..., (Offset + Is2)...>;
        };
    }
     
    template <std::size_t N, std::size_t E>
    using gen_seq = typename detail::concat_seq<typename std::make_index_sequence<E>, E + 1, typename std::make_index_sequence<(N > E) ? (N - E - 1) : 0>>::type;
     
    static_assert(std::is_same_v<std::index_sequence<0, 1,    3, 4>, gen_seq<5, 2>>);
    static_assert(std::is_same_v<std::index_sequence<   1, 2      >, gen_seq<3, 0>>);
    static_assert(std::is_same_v<std::index_sequence<0, 1, 2, 3   >, gen_seq<4, 4>>);
    J'ai une question simple bien qu'un peu générale, certes : comment ça marche ? J'ai bien une vague idée de ce qu'il se passe mais j'aimerais saisir les détails. En particulier : que fait (Offset + Is2)... ?

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Salut,

    c'est du template bien velu pour générer des listes d'entiers à la compilation.
    index_sequence<0,1,2,3> crée une structure avec paramètres template de type size_t valant 0, 1, 2 et 3. Et tu as des helpers comme make_index_sequence<A> pour générer <0, ..., A-1>
    Sur SO tu peux lire que le but de gen_seq<A, B> est de générer une telle liste de 0 à A exclus en skippant B.

    Tu peux voir que concat_seq fait juste une concaténation de 2 séquences. Les séquences sont séparées par cet offset dans les paramètres qui est appliqué à chaque élément de la 2° séquence.

    Avec gen_seq<N, E> tu as
    - La première séquence est typename std::make_index_sequence<E> qui génère <0, ..., E-1>
    - E + 1 sert d'offset
    - La deuxième séquence est typename std::make_index_sequence<(N > E) ? (N - E - 1) : 0 qui génère <0, ..., N-E-2> si N > E, un ensemble vide <> sinon

    gen_seq<5, 2>
    - séquence 1 : <0, 1>
    - offset : 2+1=3
    - séquence 2 : 5-2-1=2 : <0, 1>
    en concaténant le tout on retrouve <0, 1, 0+3, 1+3> = <0, 1, 3, 4>
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Oui d'accord, je vois à peu près. Ma confusion vient du fait qu'instinctivement j'aurais cherché à implémenter la solution différemment, sans doute à base de tag dispatch ou d'enable_if.. J'ai probablement une vision un peu trop « impérative » de la chose.

    Donc (Offset + Is2)... applique Offset + à tous les éléments de la séquence Is2, ok.

    Il y a encore un point qui m'échappe, les lignes 8 et 9 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        template         <std::size_t            ...Is1, std::size_t Offset, std::size_t            ...Is2>
        struct concat_seq<std::index_sequence<Is1...>  ,             Offset, std::index_sequence<Is2...>  >
    S'agit-il d'une spécialisation ? Pourquoi les paramètres templates sont-ils ainsi « répétés » et comment sont-ils sélectionnés/appliqués lors de la déclaration de gen_seq ?

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Tu ne peux normalement pas avoir 2 variadic template dans un template. Logiquement, puisque ... englobe déjà tous les paramètres.
    Pour contourner cette limite, on ne passe pas directement les paramètres template mais la struct index_sequence (qui prend des variadic template et doivent donc être déclarés).
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Je n'ai pas encore vraiment eu le temps de me remettre au travail sur la branche en question mais je pense avoir mieux saisi la syntaxe utilisée, merci.

    J'ai implémenté une petite variation qui me permet de générer une répétition d'un même entier encadrée par deux autres entiers :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #include <climits>
    #include <type_traits>
    #include <utility>
     
     
    namespace detail {
        template <typename T, std::enable_if_t<std::is_integral_v<T>, T> Filler, T Prefix, std::size_t N, T ...Elements>
        struct repeat_seq {
            using type = typename repeat_seq<T, Filler, Prefix, N - 1, Filler, Elements...>::type;
        };
     
        template <typename T, std::enable_if_t<std::is_integral_v<T>, T> Filler, T Prefix, T ...Elements>
        struct repeat_seq<T, Filler, Prefix, std::size_t(0u), Elements...> {
            using type = std::integer_sequence<T, Prefix, Elements...>;
        };
    }
     
    template <int Prefix, int Filler, std::size_t N, int Suffix>
    using gen_seq = typename detail::repeat_seq<int, Filler, Prefix, N, Suffix>::type;
     
     
    static_assert(std::is_same_v<std::integer_sequence<int, INT_MIN, 42, 42, 42, 42, 42, INT_MAX>, gen_seq<INT_MIN, 42, 5, INT_MAX>>);
    Ce que je veux est au final un poil plus complexe mais cela fera l'affaire pour l'instant ; j'y viendrais peut-être dans un futur post.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 15
    Dernier message: 15/12/2006, 18h18
  2. Css : Fond transparent d'un tableau s'applique aux images
    Par Orionmel dans le forum Mise en page CSS
    Réponses: 15
    Dernier message: 07/07/2006, 09h02
  3. appliquation aux maths..
    Par yakamone3 dans le forum Mathématiques
    Réponses: 8
    Dernier message: 07/06/2006, 20h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo