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 :

boucle for métaprog


Sujet :

C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 301
    Points : 345
    Points
    345
    Par défaut boucle for métaprog
    Bonjour à tous,

    Je voudrais à la compilation créer la liste des types formés d'un type de chacune de deux listes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    typedef mpl::vector<bool, char> list_types_1;
    typedef mpl::vector<short, int, long> list_types_2;
    avec comme resultat la liste suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    template<typename T1, T2>
    struct Foo {};
     
    mpl::vector<
    	Foo<bool, short>,
    	Foo<bool, int>,
    	Foo<bool, long>,
    	Foo<char, short>,
    	Foo<char, int>,
    	Foo<char, long> > list_types_3;
    en gros faire une double boucle for :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    foreach type1 in list_types_1
    	foreach type2 in list_types_2
    		mpl::push_back< list_types_3, Foo<type1, type2> >
    mais je vois pas trop comment procéder (je débute total en métaprog )

  2. #2
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    boost::mpl::joint_view
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 301
    Points : 345
    Points
    345
    Par défaut
    de ce que j'ai vu de la doc de boost joint_view ce serait plus pour faire un truc du style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef mpl::vector<bool, char, short, int, long> list_types_3;
    non?

  4. #4
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Je ne sais pas ce que propose boost, mais tu peus toujours le refaire toi même, définit proprement l'aglo sur papier (en récursif, plus simple pour la méta-prog je trouve), et code le.

    Je te fais un petit exemple qui est un cas réduit du tiens, on suppose une liste de type et un type fixé et on va construire tout les paires entre l'élément et la liste.

    Algo:
    Cas général, on prend le premier élément de la liste et on fait une pair avec le type fixé, on applique l'algo au reste de la liste, et on mets les deux bout à bout.
    Cas terminal, la liste est vide, on retourne une liste vide.

    Code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    template<class List, class T> struct do_pair;
     
    template<class H, class T, class T>
    struct do_pair<TypeList<Head, Tail>, T>
    {
        typedef pair<T, Head> NewHead;
        typedef typename do_pair<T, Tail>::Result NewTail;
        typedef TypeList<NewHead, NewTail> Result;
    };
     
    template<class T>
    struct do_pair<NullType, T>
    { typedef NullType Result; };
    Edit post message de Joel: J'ai bien dis que je savais pas ce que proposais boost, mais c'etait certain qu'en l'utilisant ca serait mieux qu'un code fait en 2 min sur le forum J'ai proposé ca pour l'approche algorithme du problème.

  5. #5
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Y a mieux et plus simple.
    C'est un produit cartesien de liste, donc un fold O fold :

    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
     
     
    #include <boost/mpl/fold.hpp>
    #include <boost/mpl/vector.hpp>
    #include <boost/mpl/push_back.hpp>
    #include <boost/mpl/placeholders.hpp>
     
    namespace unit
    {
      //////////////////////////////////////////////////////////////////////////////
      // meta-cartesian product
      //////////////////////////////////////////////////////////////////////////////
      template<class S1, class S2> struct cartesian_product
      {
        template<class V, class S, class State>
        struct inner
        {
          typedef typename boost::mpl::fold<S
                                           , State
                                           , boost::mpl::push_back< boost::mpl::_1
                                                                  , std::pair<V
                                                                             ,boost::mpl::_2
                                                                             >
                                                                  >
                                           >::type type;
        };
     
        typedef typename boost::mpl::fold<S1
                                         , boost::mpl::vector<>
                                         , inner<boost::mpl::_2, S2, boost::mpl::_1>
                                         >::type type;
      };
    J'ai la flemme mais on peut rempalcer std::pair par un type template façon Foo<_1,_2> et le passer via un apply2

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 301
    Points : 345
    Points
    345
    Par défaut
    Merci Joel pour ton code, je me suis un peu arraché les cheveux hier pour le comprendre mais finalement après une bonne nuit de sommeil c'est maintenant très clair, je l'ai complété pour qu'il prenne en paramètre une méta-fonction:

    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
     
    //////////////////////////////////////////////////////////////////////////////
    // meta-cartesian product
    //////////////////////////////////////////////////////////////////////////////
    template<class S1, class S2, class Func > struct cartesian_product
    {
    	template<class V, class S, class State, class F>
    	struct inner
    	{
    		typedef typename boost::mpl::fold<
    				S
    				, State
    				, boost::mpl::push_back<
    					boost::mpl::_1
    					, typename boost::mpl::apply<F, V, boost::mpl::_2>::type
    					>
    				>::type type;
    	};
     
    	typedef typename boost::mpl::fold<
    			S1
    			, boost::mpl::vector<>
    			, inner<boost::mpl::_2, S2, boost::mpl::_1, Func>
    			>::type type;
    };
    avec le test suivant:

    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
     
    struct MyFunction
    {
    	template<typename T1, typename T2>
    	struct apply
    	{
    		typedef Foo<T1, T2> type;
    	};
    };
     
    typedef boost::mpl::vector<bool, char> v1;
    typedef boost::mpl::vector<short, int> v2;
     
    typedef cartesian_product<v1, v2, MyFunction>::type result;
     
    BOOST_MPL_ASSERT(( boost::is_same< boost::mpl::at_c<result, 0>::type, Foo<bool, short> >));
    BOOST_MPL_ASSERT(( boost::is_same< boost::mpl::at_c<result, 1>::type, Foo<bool, int> >));
    BOOST_MPL_ASSERT(( boost::is_same< boost::mpl::at_c<result, 2>::type, Foo<char, short> >));
    BOOST_MPL_ASSERT(( boost::is_same< boost::mpl::at_c<result, 3>::type, Foo<char, char> >)); //ici problème de compilation: Foo<char, char> != Foo<char, int>
    Par contre j'ai plusieurs questions:
    (1) Est-il possible de comparer directement result avec un mpl::vector< Foo<bool, short>, Foo<bool, int>, Foo<char, short>, Foo<char, int> >
    (2) Peut-on se passer d'écrire la méta-fonction MyFunction (en faisant un truc du genre des lambda: une méta-fonction non nommée qu'on utiliserai directement lors de typedef cartesian_product<v1, v2, MyFunction>::type result)

  7. #7
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Citation Envoyé par CedricMocquillon Voir le message
    de ce que j'ai vu de la doc de boost joint_view ce serait plus pour faire un truc du style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef mpl::vector<bool, char, short, int, long> list_types_3;
    non?
    Désolé j'avais mal lu l'énoncé, (ça m'apprendra a poster quand j'en ai pas le temps).

    (1) : boost::mpl::equal

    (2) : A première vu oui mais j'ai pas le temps (encore...) de pondre un code là.
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  8. #8
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par CedricMocquillon Voir le message
    (2) Peut-on se passer d'écrire la méta-fonction MyFunction (en faisant un truc du genre des lambda: une méta-fonction non nommée qu'on utiliserai directement lors de typedef cartesian_product<v1, v2, MyFunction>::type result)
    Oui, attention c'est du lourd:

    n'importe quelle classe template ou apparait un _n en parametre devient une lambda.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    typedef cartesian_product<v1, v2, Foo<boost::mpl::_1, boost::mpl::_2> >::type result;

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 301
    Points : 345
    Points
    345
    Par défaut
    Grande classe! Merci à tous pour votre aide

  10. #10
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Citation Envoyé par Joel F Voir le message
    Oui, attention c'est du lourd:

    n'importe quelle classe template ou apparait un _n en parametre devient une lambda.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    typedef cartesian_product<v1, v2, Foo<boost::mpl::_1, boost::mpl::_2> >::type result;
    Ok, j'avais encore pas du tout regardé le bon code...

    bon faut que j'aille dormir moi...

    *hey tyler, ça marche les savons* ?
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  11. #11
    Débutant
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Points : 176
    Points
    176
    Par défaut
    et ça peut avoir un intérêt ce code lol ?

  12. #12
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Citation Envoyé par guillaume07 Voir le message
    et ça peut avoir un intérêt ce code lol ?
    Tu comptes demander si la méta-prog à un interet à chaque fois que tu vois un exemple ?

    Construire toute les paires possibles d'éléments d'une liste de types pourrait par exemple avoir une utilité pour résoudre du multi-dispatch. Et surment plien d'autre exemple.

  13. #13
    Débutant
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Points : 176
    Points
    176
    Par défaut
    à chaque fois que je n'en verrais pas un intérêt direct oui tant pis si tu m'aimes pas

  14. #14
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    D'accord, je vais essayer d'apporter une réponse plus complète alors

    La méta-prog n'est pas en soi essentiel, mais elle apporte une généricité plus grande qui peut se révéler très utile.

    Si tu as le temps, écris un code qui doit visiter une hiérachie : visiteur ou multi-methodes par exemple, une fois normalement, une fois avec de la méta-prog, puis modifie chacun de tes codes pour rajouter une classe dans la hiérarchie, tu devrais sentir l'utilité.

    Mais la TMP est un langage en soi, dont le code est executé directement par le compilateur. En tant que langage, tout problème que tu peus te poser en C++ (classique) peut avoir lieux d'être en TMP.

    Dans le cas de l'OP c'est donc se demander quel est l'utilité de contruire un vecteur de paires, à partir d'une vecteur, qui contient toute les pairs possibles du premier vecteur. Et sans exemples je suis presque certain que tu en concois que ca peut servir. C'est pareil en TMP.

    Mathématiquement, comme l'a souligné Joel, c'est un produit cartésien d'un ensemble finie par lui-même. Donc en C++ (classique) comme en TMP, ca peut servir dans un porgramme mathématique pour représenter un ensemble de type E² (avec E finie), et par extension à tout algorithme mathématique qui se ramène à un problème mathématique basé sur E².

  15. #15
    Débutant
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Points : 176
    Points
    176
    Par défaut
    ok merci j'essayerais l'histoire du visteur

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

Discussions similaires

  1. Boucle for dans un script cmd
    Par nicolas.ganache dans le forum Développement
    Réponses: 4
    Dernier message: 19/07/2004, 16h07
  2. Réponses: 3
    Dernier message: 06/07/2004, 10h21
  3. [Debutant] Batch et Boucle for
    Par ludovic.fernandez dans le forum Scripts/Batch
    Réponses: 8
    Dernier message: 06/05/2004, 19h21
  4. [Swing][boucles] for, do, if .....comment faire simple?
    Par chastel dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 02/05/2004, 22h49
  5. [langage] boucle "for" modification du pas
    Par K-ZimiR dans le forum Langage
    Réponses: 4
    Dernier message: 29/04/2004, 11h54

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