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

C++ Discussion :

Variadic template et polices


Sujet :

C++

  1. #1
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Santé

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Par défaut Variadic template et polices
    Bonjour tout le monde,

    Je cherche à partir d'une classe qui hérite de plusieurs polices avec la même méthodes:
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    #include <iostream>
     
    template<typename PolicyOne, typename PolicyTwo>
    class Test : public PolicyOne, public PolicyTwo
    {
      void run()
      {
        PolicyOne::run();
        PolicyTwo::run();
      }
    };
     
    class PolicyA
    {
      void run()
      {
        std::cout << "PolicyA" << std::endl;
      }
    };
     
    class PolicyB
    {
      void run()
      {
        std::cout << "PolicyB" << std::endl;
      }
    };
     
    int main(int argc, char* argv[])
    {
      Test<PolicyA, PolicyB> t1;
      t1.run(); // Affiche PolicyA\nPolicyB
      return 0;
    }
    Je voudrais maintenant "généraliser" un peu ce type de comportement en ayant un nombre "illimité" de polices (ayant toutes le même nom de méthode). J'ai donc pensé au variadic templates avec l'implémentation suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template<typename... Policies>
    class Test : public Policies...
    {
       void run()
       {
         //Que mettre ici??? Policies...::run()?
       }
    };
    Je ne sais pas comment parcourir l'ensemble de mes classes Policies. Peut-on utiliser une lambda fonction?

    Merci pour tout!

  2. #2
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Citation Envoyé par darkman19320 Voir le message
    Je ne sais pas comment parcourir l'ensemble de mes classes Policies. Peut-on utiliser une lambda fonction?

    Merci pour tout!
    Ça me parait possible avec une classe template PolicyExecutor (qui serait donc « friend » de ta classe Test si run est privée), et une récursion du coup classique sur les politiques.

    Quelque chose comme (écrit à la volée, sans garantie):
    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
     
    template<typename T>
    struct PolicyExecutor
    {
        static void exec(Test& t)
        {
             static_cast<T&>(t).run();
        }
    };
     
    template<typename T, typename... Args>
    struct PolicyExecutor
    {
        static void exec(Test& t)
        {
             PolicyExecutor<T>::exec(t);
             PolicyExecutor<Args...>::exec(t);
        }
    }

  3. #3
    Membre Expert
    Avatar de prgasp77
    Homme Profil pro
    Ingénieur en systèmes embarqués
    Inscrit en
    Juin 2004
    Messages
    1 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 306
    Par défaut
    Il va falloir procéder par récursion. Quelque chose comme ça (je ne me souviens plus de la syntaxe) :
    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
    template<>
    class Test<void>
    {
        void run() {}
    };
     
    template<class PolicyHead, class... PolicyTail>
    class Test : public PolicyHead, public Test<PolicyTail...>
    {
        void run()
        {
             PolicyHead::run();
             Test<PolicyTail...>::run();
        }
    };

  4. #4
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Santé

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Par défaut
    Merci. Grace à vos deux réponses j'ai réussi.

    Voici la syntaxe correcte:

    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    #include <iostream>
     
    class PolicyA
    {
    public:
    	void run()
    	{
    		std::cout << "PolicyA" << std::endl;
    	}
    };
     
    class PolicyB
    {
    public:
    	void run()
    	{
    		std::cout << "PolicyB" << std::endl;
    	}
    };
     
    template<typename PolicyHead, typename... PolicyTail>
    class Test : public PolicyHead, public Test<PolicyTail...>
    {
    public:
    	void run()
    	{
    		PolicyHead::run();
    		Test<PolicyTail...>::run();
    	}
    };
     
    template<typename Policy>
    class Test<Policy>: public Policy
    {
    public:
    	void run()
    	{
    		Policy::run();
    	}
    };
     
    int main(int argc, char* argv[])
    {
    	Test<PolicyA, PolicyB, PolicyA, PolicyA, PolicyB> t1;
    	t1.run(); // Affiche PolicyA \n PolicyB \n PolicyA \n PolicyA \n PolicyB
    	return 0;
    }
    Bien évidemment, il faut un compilo qui accepte les variadic templates...

  5. #5
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void run() {
        (void)std::initializer_list<int>{(void(static_cast<Policies&>(*this).run()), 1)...};
    }
    ou s'il n'y a pas d'héritage:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void run() {
        (void)std::initializer_list<int>{(void(Policies::run()), 1)...};
    }

  6. #6
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Santé

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Par défaut
    @jo_link_noir: merci pour ta réponse. J'ai une petite question pourquoi tu as mis des cast void? Je viens de tester sans les casts: le code compile et fonctionne de la même manière.

  7. #7
    Membre Expert
    Avatar de prgasp77
    Homme Profil pro
    Ingénieur en systèmes embarqués
    Inscrit en
    Juin 2004
    Messages
    1 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 306
    Par défaut
    Ce ne sont pas des cast ; ils sont là pour ignorer explicitement les valeurs de retour. Ton objectif est d'appeler les Policies::run() ; et l'astuce trouvée par jo_link_noir passe par la construction d'une std::initialization_list<int> ; objet qui doit être disposé, on le fait donc de manière explicite, améliorant la lisibilité du code et supprimant le warning de compilation (-Wunused-value). Le second est plus subtile, tellement que je ne suis pas sûr de moi : on ignore le résultat de Policies::run() avec l'operator, et on retourne la constante 1 ; à nouveau expliciter la disposition du retour aide à la lisibilité. Qui plus est, si les méthodes run() devaient retourner quelque chose à l'avenir, cette ligne est toujours valable.

    Corrigez-moi si je me trompe.

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

Discussions similaires

  1. Hierarchie et variadic template
    Par victor_gasgas dans le forum Langage
    Réponses: 5
    Dernier message: 22/09/2010, 17h24
  2. C++ 0x variadic template
    Par victor_gasgas dans le forum Langage
    Réponses: 6
    Dernier message: 21/09/2010, 07h26
  3. [C++0x] Variadic template : un constructeur par type
    Par Florian Goo dans le forum Langage
    Réponses: 2
    Dernier message: 08/04/2009, 18h33
  4. Réponses: 2
    Dernier message: 10/01/2009, 13h38

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