SlideShare ist ein Scribd-Unternehmen logo
1 von 50
MetaProgrammation C++
type list multidimmensionnelle


                        Vincent Agnus,
Institut de Recherche contre les Cancers de l'Appareil Digestif
                      Developer Forum 4
                      18 septembre 2008
                          Strasbourg
                                             University of Strasbourg, France
Présentation
 MetaProgrammation    C++
 Typelist & Dispatcher
 Discussion




         Vincent Agnus                  3/50
Meta Programmation C++
   Meta Programmation =
    « génération par le compilateur d'algorithmes dans le
    code source »
   Language compilé : C++, Curl, D, Eiffel, Haskell, ML and XL.
   Language interprété : modifiable pdt runtime
   C++ MetaProgrammation : basée sur les templates




              Vincent Agnus                               4/50
Meta Programmation C++
                        Template
   Permet de définir des fonctions génériques --> comportement
    commun
     #include <iostream>

     template <typename T>
     inline const T& maximum(const T& x,const T& y)
     {
        if(y > x)
           return y;
        else
           return x;
     }


     int main(void)
     {
        // template instanciation
        std::cout << maximum<int>(3,7) << endl;   //outputs 7
        std::cout << maximum(3, 7) << endl;       //same as above
        std::cout << maximum(3.2,7.3) << endl;    //outputs 7.3
        return 0;
     }


                 Vincent Agnus                                      5/50
Template C++
   Spécialisation de templates --> comportement particulier

     #include <iostream>
     #include <string>

     template<>
     inline const std::string& maximum(const std::string& x,const std::string& y)
     {
        if( y.size() > x.size() )
           return y;
        else
           return x;
     }


     int main(void)
     {
        std::cout << maximum<int>(3,7) << endl;        //sortie 7
        std::string s1(''court'');
        std::string s2(''trestreslong'');
        std::cout << maximum(s1, s2) << endl;       // sortie trestreslong
        return 0;
     }

                 Vincent Agnus                                            6/50
Meta Programmation C++
                        Template
   Classe gérant des types/valeurs génériques

     template<typename T>
     class MyVector
     {
         ...
     protected :
         int m_nbElements;
         T *m_elements;
     };



     template<typename T, int N> // ici un template du genre valeur
     class MyArray
     {
         ...
     protected :
         T[N] m_elements;
     };




                 Vincent Agnus                                        7/50
Meta Programmation C++
                        Template
   Les templates lors de la compilation génèrent du code
    temporaire qui est inséré dans le code source qui est
    recompilé
   Metaprogrammation à partir des templates
       Génération de classes à la compilation
       Optimisation de code à la compilation
       Définition de nouveaux idioms




                 Vincent Agnus                              8/50
Meta Programmation C++
                         Template
   Génération de classe




     int factoriel(int n)
     {
         return (n==0?1:n*factoriel(n-1));
     }


     void foo()
     {
       // 4 est connu au moment de la compilation
       int y = factoriel(4);          // valeur calculée à chaque l'exécution !!!
     }


                  Vincent Agnus                                                9/50
Meta Programmation C++
                         Template
   Génération de classe
     template <int N>
     struct Factoriel
     {
         enum { value = N * Factoriel<N - 1>::value };
     };

     template <>
     struct Factoriel<0>
     {
         enum { value = 1 };
     };

     int factoriel(int n)
     {
         return (n==0?1:n*factoriel(n-1));
     }


     void foo()
     {
       int x = Factoriel<4>::value; //== 24 constante générée lors de la compilation
       int y = factoriel(4);          // valeur calculée lors de l'exécution
     }

                  Vincent Agnus                                                10/50
Meta Programmation C++
                        Template
   Optimisation de Code
     template<class T, int N>
     class MyArray
     {
         typedef MyArray<T,N> Self;

         Self &operator+=(const Self& rhs)
         {
             for (int i = 0; i < N; ++i)
             { m_elements[i] += rhs.value[i]; } // N connu => boucle déroulable
             return *this;
         }

     protected :
         T[N] m_elements;
     };


   Compilatation : myArrayInstance        +=    myArrayInstance2;
       N connu lors de la compilation
       le compilateur peut dérouler la boucle
       Créer du code parallélisable
                 Vincent Agnus                                           11/50
Meta Programmation C++
                         Template
   Créer des idioms
   Exemple «Polymorphisme statique» ou «Curiously Recurring
    Template Pattern»
    template <typename DERIVED>
    struct base
    {
        // ...
    };

    struct derived : base<derived>
    {
        // ...
    };


   Objectif :
       Ajout de fonctionnalités à une classe
       Dérivation sans utilisation de table de virtualité

                  Vincent Agnus                              12/50
Meta Programmation C++
                        Template
   Curiously Recurring Template Pattern--Polymorphisme statique
      template <class DERIVED>
      struct Base
      {
          void interface()
          {
              // ...
              static_cast<DERIVED*>(this)->implementation();
              // ...
          }

           static void static_func()
           {
               // ...
               Derived::static_sub_func();
               // ...
           }
      };

      struct Derived : Base<Derived>
      {
          void implementation();
          static void static_sub_func();
      };

                 Vincent Agnus                                     13/50
Meta Programmation C++
                          Template
    Curiously Recurring Template Pattern-- exemple 1
    template <typename T>
    struct counter                                         class X : counter<X>
    {                                                      {
        counter()                                              // ...
        {                                                  };
            objects_created++;
            objects_alive++;                               class Y : counter<Y>
        }                                                  {
                                                               // ...
       virtual ~counter()                                  };
       {
           --objects_alive;
       }
       static int objects_created;
       static int objects_alive;
    };
    template <typename T> int counter<T>::objects_created( 0 );
    template <typename T> int counter<T>::objects_alive( 0 );




                   Vincent Agnus                                          14/50
Meta Programmation C++
                          Template
    Curiously Recurring Template Pattern -- Exemple 2

    // A class template to express an equality comparison interface.
    template<typename T> class equal_comparable
    {
        friend bool operator==(T const &a, T const &b) { return a.equal_to(b); }
        friend bool operator!=(T const &a, T const &b) { return !a.equal_to(b); }
    };


    class value_type
     // Class value_type wants to have == and !=, so it derives from
     // equal_comparable with itself as argument (which is the CRTP).
     : private equal_comparable<value_type>
    {
      public:
        bool equal_to(value_type const& rhs) const; // to be defined
    };




                   Vincent Agnus                                           15/50
MetaProgrammation C++
   Avantages – Inconvénients :
       Générique
       Temps compilation – Performance lors runtime
       Maintenance
       Portabilité
         • Différent compilateurs
       Lisibilité :
         • syntaxe
         • message d'erreurs


   Bibliothèque C++ : boost meta programming Language



    http://www.boost.org/doc/libs/release/libs/mpl/
                       Vincent Agnus                     16/50
Type List & Dispatcher




Vincent Agnus                        17/50
Type List & Dispatcher
   Objectif : Automatisation écriture de code pour la gestion de
    plusieurs types/classes
       Exemples
   problématique IRCAD
   Principe de la solution mise en place
   Détail de l'implémentation
   Discussion




               Vincent Agnus                                18/50
Type List & Dispatcher
                      Motivation
   class Shape {...};
    class Point : public Shape {...};
                                            Exemple une Fabrique
    class Ball : public Shape {...};

    template<T> T *create()
    {
        return new T;
    }

    class TrivialShapeFactory
    {
        static Shape *build(std::string &key)
        {
            if ( key == "Point" )
            {
                return create<Point>();
            }
            else if ( key == "Ball" )
            {
                return create<Ball>();
            }
        }
    };
              Vincent Agnus                               19/50
Type List & Dispatcher
                            Motivation
   Plus de degrés de liberté
    class Shape {...};
    class Point : public Shape {...};
    class Ball : public Shape {...};

    class   Color   {...};
    class   Red     : public Color {...};
    class   Green   : public Color {...};
    class   Blue    : public Color {...};

    template< class COLOR, class SHAPE >
    class ColoredShape : public SHAPE
    {
        // ....
        COLOR m_color;
    };

    template< COLOR, SHAPE> Shape *createColoredShape()
    {
        return new ColoredShape< COLOR , SHAPE >;
    }

                    Vincent Agnus                         20/50
Type List & Dispatcher
                        Motivation
   La nouvelle fabrique à 2 degrés de liberté
class ColoredShapeFactory
{
  static Shape *build(std::string &color, std::string &shape)
    {
      if ( shape == "Point" )
      {
        if ( color == "Red" )   { return createColoredShape<Red,   Point>();}
        if ( color == "Green") { return createColoredShape<Green, Point>();}
        if ( color == "Blue" ) { return createColoredShape<Blue, Point>();}
      }
      else if ( shape == "Ball" )
      {
    if ( color == "Red" )    { return createColoredShape<Red,   Ball>();}
            // and so on ...
      }
        ...
    }
};

   Ajout d'une nouvelle classe -> risque d'erreurs
   Typelist --> automatisation
                Vincent Agnus                                       21/50
Type List & Dispatcher
                        Motivation
   Motivation « IRCAD »
   Utilisation de la librairie template ITK
       template <typename PIXELTYPE, int DIM>
        itk::Image<PIXELTYPE,DIM>

       template <typename TImageIn, typename TImageOut>
        itk::ImageFilter<TImageIn,TImageOut>
   Nous utilisons des types images non templates (conversion <->
    ITK )
       void *m_buffer;
       PixelType m_pixelType;
   Il faut gérer les entrées/sorties des filtres avec des images de
    différents types

                Vincent Agnus                                22/50
Type List & Dispatcher
                      Mise en Oeuvre
   Automatisation l'écriture du code
   MetaProgrammation C++ :
       Typelist : définir la liste des types à traiter
       Le Dispatcher qui va parcourrir cette liste
       Mapping entre Type de la typelist et Type requis lors du runtime
       Functor (traitement)
       Gestion des type list n-dimensionnelles
   Cas d'utilisation : Dispatcher sur Fabriques




                 Vincent Agnus                                        23/50
Type List & Dispatcher
                    définition d'une type list
   Type List = « Un container qui contient des types »
   La boost MPL fournit plusieurs type de typelist

    #include<vector>
    #include<boost/mpl/vector.hpp>
    #include<boost/mpl/at.hpp>

    void f()
    {
       std::vector<int> classicContainer(10);

        int i = classicContainer.at(1);


        typedef boost::mpl::vector< char , std::string, int > TypeList;

        typedef boost::mpl::at_c< TypeList, 1 >::type StringType;

        StringType v = ''toto''; // OK !
    }

                  Vincent Agnus                                       24/50
Type List & Dispatcher
                           Cas d'utilisation
   Dispatcher & Fabrique a 1 degré de liberté
    #include <boost/mpl/vector.hpp> // used to define type list
    #include <Dispatcher.hpp> // define our dispatcher




    struct ShapeFactory
    {
       static Shape *build(std::string key)
       {/
          // type list of supported types
          typedef boost::mpl::vector<Point,Ball> GeneratedShapeTypeList;


             Shape *shape=NULL;
             Dispatcher< GeneratedShapeTypeList, ShapeGenerator >::invoke(key,shape);
             return shape;
         }
    };               Vincent Agnus                                          25/50
Type List & Dispatcher
                           Cas d'utilisation
   Dispatcher & Fabrique a 1 degré de liberté
    #include <boost/mpl/vector.hpp> // used to define type list
    #include <Dispatcher.hpp> // define our dispatcher

    struct ShapeGenerator
    {
        template<class T>
        void operator()(Shape * &t) // we use a reference on a pointer to modify it
        {
            t=new T;
        }
    };

    // Correspondance valeur clef <--> type ( fonction IsMapping )
    // exemple chaine ''Point'' avec le type Point

    struct ShapeFactory
    {
       static Shape *build(std::string key)
       {/
          // type list of supported types
          typedef boost::mpl::vector<Point,Ball> GeneratedShapeTypeList;

             Shape *shape=NULL;
             Dispatcher< GeneratedShapeTypeList, ShapeGenerator >::invoke(key,shape);
             return shape;
         }
    };               Vincent Agnus                                                    26/50
Type List & Dispatcher
                       Cas d'utilisation
   Correspondance valeur clef <--> Type
    #include <TypeMapping.hpp>
    // used to define binding between key value and concrete type
    // define template isMapping function
    //template<typename TYPE,KEYTYPE>
    //bool isMapping<TYPE>(const KEYTYPE &key)
    //{
    //    // mandatory template specialization requested
    //    // missing binding declaration involve compilation fail
    //}



    template<> bool isMapping<Point>(const std::string &key)
    {
        return key == "Point";
    }

    template<> bool isMapping<Ball>(const std::string &key)
    {
        return key == "Ball";
    }

                 Vincent Agnus                                      27/50
Type List & Dispatcher
                        Cas d'utilisation
   Code Généré Compilation de
    Dispatcher< GeneratedShapeTypeList, ShapeGenerator >::invoke(key,shape);

   Ps e u d o Co d e Gé n é ré
    {
        // generated at compile time
           if ( isMapping< Point , std::string >(key) )
        {
            ShapeGenerator shapeGenerator;
            shapeGenerator.operator<Point>( shape );
        }
        else if ( isMapping< Ball , std::string >(key) )
        {
            ShapeGenerator shapeGenerator;
            shapeGenerator.operator<Ball>( shape );

        }
        ... // same for each type stored in    GeneratedShapeTypeList
    }




                  Vincent Agnus                                          28/50
Type List & Dispatcher
                        Cas d'utilisation
   API du Dispatcher
   Généricité vis à vis
        Nature clef
        Functor
        Type du container de la TypeList
    // file Dispatcher.hpp
    template<class MANAGEDTYPELIST, class      FUNCTOR>
    class Dispatcher
    {
        static void invoke();

          template<class KEYTYPE>
          static invoke(const KEYTYPE &key);

          template<class KEYTYPE,class PARAMETER>
          static invoke(const KEYTYPE &key, PARAMETER &param);
    };
                  Vincent Agnus                             29/50
Type List & Dispatcher
                            Cas d'utilisation
   Dispatcher & Fabrique a 2 degrés de liberté
    #include <Combinatory.hpp> // contain our meta-function cartesianProduct

    // isMapping specialized for Colors
    // isMapping for Combinaisont Type auto managed
    // functor ColoredShapeGenerator;

    struct ColoredShapeFactory
    {
        static Shape *build(std::string shape, std::string color)
        {
           //define two type lists for shape and color
           typedef boost::mpl::vector< Point, Ball >::type ManagedShape;
           typedef boost::mpl::vector< Red, Green, Blue >::type ManagedColor;

             // create the 2-dimensional typelist
             typedef boost::mpl::vector< ManagedShape, ManagedColor >::type MultiDimList;

             // generate mono-dimensional typelist with element of size 2 (shape,color)
             typedef boost::mpl::apply< CartesianProduct, MultiDimList>::type CombinaisonList;

             Shape *coloredShape=NULL;
             // generate the multi-key
             std::list< std::string > key; key.push_back(shape);key.push_back(color);

             Dispatcher< CombinaisonList , ColoredShapeGenerator >::invoke(key,coloredShape);
             return coloredShape;
         }
    };
                      Vincent Agnus                                                     30/50
Type List & Dispatcher
                          Cas d'utilisation
   Dispatcher & Fabrique a 2 degrés de liberté
   Appel du Functor ColoredShapeGenerator
    Dispatcher< CombinaisonList , ColoredShapeGenerator >::invoke(key,coloredShape);



    struct ColoredShapeGenerator
    {
        template<class TYPESEQUENCE>    // paire (SHAPE,COLOR)
        void operator()(Shape * &t)
        {
           // insure is a TSEQUENCE
           BOOST_STATIC_ASSERT ( boost::mpl::is_sequence<TYPESEQUENCE>::value );

             // retreive each type in 2 sized element TYPESEQUENCE
             typedef typename boost::mpl::at_c<TYPESEQUENCE,0>::type ChoosenShape;
             typedef typename boost::mpl::at_c<TYPESEQUENCE,1>::type ChoosenColor;

             t=new ColoredShape<    ChoosenShape, ChoosenColor> ;
         }
    };


                    Vincent Agnus                                          31/50
Type List & Dispatcher
                          Cas d'utilisation
   Fabrique a 2 degrés de liberté
   Mix des 2 types list : CombinaisonList
struct ColoredShapeFactory
{
    static Shape *build(std::string shape, std::string color)
    {
       //define two type list for shape and color
       typedef boost::mpl::vector< Point, Ball >::type ManagedShape;
       typedef boost::mpl::vector< Red, Green, Blue >::type ManagedColor;

         // create the 2-dimensional typelist
         typedef boost::mpl::vector< ManagedShape, ManagedColor >::type MultiDimList;

         // generate mono-dimensional typelist with element of size 2 (shape,color)
         typedef boost::mpl::apply< CartesianProduct, MultiDimList>::type CombinaisonList;

         Shape *coloredShape=NULL;
         // generate the multi-key
         std::list< std::string > key; key.push_back(shape);key.push_back(color);

         Dispatcher< CombinaisonList , ColoredShapeGenerator >::invoke(key,coloredShape);
         return coloredShape;
     }
};


                    Vincent Agnus                                                       32/50
Type List & Dispatcher
                             Cas d'utilisation
   Implémentation utilisant la boost::mpl
   Fonction Produit Cartésien :
    génère les combinaisons (ordonnées) de plusieurs ensembles
   Produit Cartésien de n ensembles de taille si donne un
    ensemble de s1⋯sn n-uplets

   Exemple :

                                                             
                               t 1,1                   t 3,1

                               t 1,3
                                            t
                                                
                          TL1= t 1,2 , TL2= 2,1 , TL3= t 3,2
                                            t 2,2
                                                       t 3,3




                                                                                                 
                  t 1,1 , t 2,1 , t 3,1 , t 1,1 , t 2,1 , t 3,2  , t 1,1 ,t 2,1 ,t 3,3  ,
    TL1⊗TL2⊗TL3 = t 1,1 , t 2,2 , t 3,1 , t 1,1 , t 2,2 , t 3,2  , t 1,1 ,t 2,2 ,t 3,3  ,
                             ⋮                         ⋮                         ⋮
                  t 1,3 , t 2,2 ,t 3,1 , t 1,3 , t 2,2 , t 3,2 , t 1,3 ,t 2,2 ,t 3,3 
                      Vincent Agnus                                                                   33/50
Type List & Dispatcher
                         Cas d'utilisation
   Génération des combinaisons de typelist :
 ManagedShape ~ mpl::vector<Point,Ball>
 ManagedColor ~ mpl::vector<Red,Green,Bue>
   MultiDimList mpl::vector< mpl::vector<Point,Ball> mpl::vector<Red,Green,Bue> >

   Appel Meta Fonction Produit Cartesien
    typedef boost::mpl::apply< CartesianProduct, MultiDimList>::type CombinaisonList;
   Génération à la compilation de :
typedef boost::mpl::vector<
                 boost::mpl::vector<Point,    Red>,
                 boost::mpl::vector<Point,    Green>,
                 boost::mpl::vector<Point,    Blue>,
                 boost::mpl::vector<Ball ,    Red>,
                 boost::mpl::vector<Ball ,    Green,
                  boost::mpl::vector<Ball , Blue>       >::type CombinaisonList




                   Vincent Agnus                                               34/50
Type List & Dispatcher
                             Cas d'utilisation
    Dispatcher Fabrique a 3 degrés de liberté et + :
     Modification mineure du code ( couleurs )

struct ColoredShapeFactory
{
    static Shape *build(std::string shape, std::string color, std::string style)
    {
       //define two type list for shape and color
       typedef boost::mpl::vector< Point, Ball >::type ManagedShape;
       typedef boost::mpl::vector< Red, Green, Blue >::type ManagedColor;
       typedef boost::mpl::vector< Plain, WireFrame, Hidden >::type ManagedStyle;

          // create the 2-dimensional typelist
         typedef boost::mpl::vector< ManagedShape, ManagedColor , ManagedStyle>::type MultiDimList;

         // generate mono-dimensional typelist with element of size 3 (shape,color,style)
         typedef boost::mpl::apply< CartesianProduct, MultiDimList>::type CombinaisonList;

         Shape *newShape=NULL;
         // generate the multi-key
         std::list< std::string > key; key.push_back(shape);key.push_back(color);
         key.push_back(style);

         Dispatcher< CombinaisonList , 3DOFShapeGenerator >::invoke(key,newShape);
         return newShape;
     }
};
                      Vincent Agnus                                                    35/50
Type List & Dispatcher
                            Détail
   Détail d'implémentation
       Dispatcher : méthod invoke
       IsMapping n-D ( auto géré )
       CartesianProduct Meta Function




                 Vincent Agnus               36/50
Type List & Dispatcher
                            Détail
   Dispatcher : méthod invoke
       Pour chaque type dans la typelist
       Test si type et clef compatible isMapping
       Si OK Appel functor


template< class TYPELIST, class FUNCTOR >
class Dispatcher
{
        template< class KeyType, class Parameter >
        static void invoke( const KeyType &keytype, Parameter &param );
};




                 Vincent Agnus                                    37/50
Type List & Dispatcher
                            Détail
template< class TYPELIST, class FUNCTOR >
class Dispatcher {
template< class KeyType, class Parameter >
static void invoke( const KeyType &keytype, Parameter &param )
{
   namespace mpl = boost::mpl;
   typedef typename mpl::pop_front<TYPELIST>::type Tail;
   typedef typename mpl::front<TYPELIST>::type     Head;

    if ( isMapping<Head>(keytype) )
    {
       // create the functor then excute it
       FUNCTOR f;
       f.template operator()<Head>(param);
    }
    else
    {
    // compile time : recursively call other element in the list
    typedef typename mpl::eval_if< mpl::empty<Tail>,
                                   mpl::identity< EmptyTypeListAction >,
                                   mpl::identity< Dispatcher<Tail,FUNCTOR > >
                                 >::type typex;
    typex::invoke(keytype,param);
    }
}                Vincent Agnus                                       38/50
Type List & Dispatcher
                          Détail
   Compilation de
    Dispatcher<ManagedShape,GeneratorFuncor>::invoke(key,shape)
typedef mpl::vector<Point,Ball> ManagedShape;

Dispatcher<ManagedShape, GenFunctor>::invoke( key, shape)
{
   if( isMapping<Point>(key) )
   {   GenFunctor().operator<Point>()(shape);   }
   else
   {
            typedef Dispatcher< mpl::vector<Ball>, GenFunctor> typex;
            typex::invoke(key,shape);
   }
}

Dispatcher< mpl::vector<Ball>, GenFunctor>::invoke( key, shape)
{
   if ( isMapping<Ball>(key) ) { ... }
   else
   {
            // same API than Dispatcher but always throw ''Incorrect Key''
            EmptyTypeListAction::invoke(key,shape);
   }
}
               Vincent Agnus                                            39/50
Type List & Dispatcher
                            Détail
   Détail d'implémentation
       Dispatcher : méthod invoke
       IsMapping n-D ( auto géré )
       CartesianProduct Meta Function




                 Vincent Agnus               40/50
Type List & Dispatcher
                          Détail
   IsMapping : binding Type <-> valeur clef
   Robuste vis à vis oublie spécialisation -> erreur de compilation
    template<class TYPE,class KEY>
    bool isMapping<TYPE>(const KEY &key)
    {
        BOOST_STATIC_ASSERT(sizeof(TYPE) == 0)
    }
   Gestion automatique des clefs multiple càd
isMapping< mpl::vector<...> >(keys) =
isMapping< mpl::front(mpl::vector<...>) >(keys.front()) &&
isMapping< mpl::pop_front(mpl::vector<...>) >(keys.pop_front());




               Vincent Agnus                                41/50
Type List & Dispatcher
                            Détail
   Détail d'implémentation
       Dispatcher : méthod invoke
       IsMapping n-D ( auto géré )
       CartesianProduct Meta Function




                 Vincent Agnus               42/50
Type List & Dispatcher
                          Détail
   Produit cartésien est défini comme une meta fonction MPL :
    (équivalent functor C++)
     struct MaMetaFunction
     {
            template<class PARAM1, class PARAM2, ...>
            struct apply
            {
                    typedef .... type;
            };
     };



   Appel boost::mpl::apply<MetaFct,P1,...>::type est un
    typedef sur MetaFct::apply<P1,...>::type
   exemple boost::mpl::identity


               Vincent Agnus                             43/50
Type List & Dispatcher
                          Détail
   Produit Cartésien :
   Prop TL1  TL2  ...  TLn = TL1  ( TL1  (...  TLn )))

struct CartesianProduct
{
   template< class MultiSet >
   struct apply
   {
      typedef typename boost::mpl::reverse_fold<
                          MultiSet,
                          boost::mpl::vector<>,
                          boost::mpl::apply2< CartesianProduct_1_N_Recurser,
                                             boost::mpl::_2, boost::mpl::_1
                                            >
                          >::type type;
         };
};

   3 meta fonctions intermédiaires
   Au total 45 lignes
               Vincent Agnus                                           44/50
Type List & Dispatcher
                         Discussion
   Discussion
       Généricité vis à vis clef
       Spécificité de notre approche
       Retour d'expériences




                 Vincent Agnus               45/50
Type List & Dispatcher
                         Discussion
   Généricité vis à vis des clefs
       Dimension des images : utilisation de
        namespace boost {
        namespace mpl {
           template< int N >
           struct int_ { ... }:
       Gestion des Multi-méthodes :
         • Clef spéciale : struct TypeInfo { std::type_info *m_data};
         • Spécialisation :
           template<> bool isMapping<Point>(const TypeInfo &key)
           { return *key.m_data == typeid(Point); }




                 Vincent Agnus                                          46/50
Type List & Dispatcher
                         Discussion
   Spécificité de notre approche
       Gestion native des types lists multidimensionnelles
       Externalisation de la combinaison des type lists
       Statique
       Recherche clef type en O(n)




                 Vincent Agnus                                47/50
Type List & Dispatcher
                           Discussion
   Retour d'expériences
       MPL :
         •   Documentation web : boost mpl réduite
         •   Debuggeage à la compilation par STATIC_ASSERT
         •   Multi OS ( Linux, OsX, win32 ) OK
         •   paradigme programmation fonctionnelle
       MetaProgrammation C++
         • Message erreur de compilation « illisible »
         • Généricité
         • Code Utilisateur : simplifié & sécurisé




                   Vincent Agnus                             48/50
Type List & Dispatcher
                          Ressources
   Livres :
        Modern C++ Design, A. Alexandrescu. « C++ in depth series»
        C++ Template Metaprogramming, D. Abrahams, A. Gurtovoy. « C++ in
         depth series»
        C++ Templates - The Complete Guide, D. Vandevoorde et N. Josuttis.
         Addison-Wesley
   Article :
        En cours rédaction : « Multi-Dimensional C++ Type List » pour revue
         « Computer Languages, Systems & Structures » Ed. Elsevier
   Distribution des sources ?




                  Vincent Agnus                                       49/50
Merci pour votre attention




Vincent Agnus                            50/50

Weitere ähnliche Inhalte

Was ist angesagt?

Les nouveautés de C++11 : Ecrire du C++ Moderne
Les nouveautés de C++11 : Ecrire du C++ ModerneLes nouveautés de C++11 : Ecrire du C++ Moderne
Les nouveautés de C++11 : Ecrire du C++ ModerneMicrosoft
 
Corrigés exercices langage C
Corrigés exercices langage CCorrigés exercices langage C
Corrigés exercices langage Ccoursuniv
 
C# et .NET : Enigmes et puzzles
C# et .NET : Enigmes  et puzzlesC# et .NET : Enigmes  et puzzles
C# et .NET : Enigmes et puzzlesMicrosoft
 
Cours langage c
Cours langage cCours langage c
Cours langage ccoursuniv
 
Développer en natif avec C++11
Développer en natif avec C++11Développer en natif avec C++11
Développer en natif avec C++11Microsoft
 
Chapitre1: Langage Python
Chapitre1: Langage PythonChapitre1: Langage Python
Chapitre1: Langage PythonAziz Darouichi
 
Chapitre 11: Expression Lambda et Référence de méthode en Java
Chapitre 11: Expression Lambda et Référence de méthode en JavaChapitre 11: Expression Lambda et Référence de méthode en Java
Chapitre 11: Expression Lambda et Référence de méthode en JavaAziz Darouichi
 
Chapitre4: Pointeurs et références
Chapitre4: Pointeurs et références Chapitre4: Pointeurs et références
Chapitre4: Pointeurs et références Aziz Darouichi
 
Chap1V2019: Cours en C++
Chap1V2019: Cours en C++Chap1V2019: Cours en C++
Chap1V2019: Cours en C++Aziz Darouichi
 
Exercices en langage c
Exercices en langage cExercices en langage c
Exercices en langage cDaoua Lotfi
 
C1 - Langage C - ISIMA - Première partie
C1 - Langage C - ISIMA - Première partieC1 - Langage C - ISIMA - Première partie
C1 - Langage C - ISIMA - Première partieLoic Yon
 
Cours structures des données (langage c)
Cours structures des données (langage c)Cours structures des données (langage c)
Cours structures des données (langage c)rezgui mohamed
 
Langage C
Langage  CLangage  C
Langage Cjwilili
 
Tp1 compte rendu en langage c
Tp1 compte rendu en langage cTp1 compte rendu en langage c
Tp1 compte rendu en langage cEbrima NJIE
 

Was ist angesagt? (20)

Les nouveautés de C++11 : Ecrire du C++ Moderne
Les nouveautés de C++11 : Ecrire du C++ ModerneLes nouveautés de C++11 : Ecrire du C++ Moderne
Les nouveautés de C++11 : Ecrire du C++ Moderne
 
Corrigés exercices langage C
Corrigés exercices langage CCorrigés exercices langage C
Corrigés exercices langage C
 
C# et .NET : Enigmes et puzzles
C# et .NET : Enigmes  et puzzlesC# et .NET : Enigmes  et puzzles
C# et .NET : Enigmes et puzzles
 
Cours langage c
Cours langage cCours langage c
Cours langage c
 
Développer en natif avec C++11
Développer en natif avec C++11Développer en natif avec C++11
Développer en natif avec C++11
 
Chapitre1: Langage Python
Chapitre1: Langage PythonChapitre1: Langage Python
Chapitre1: Langage Python
 
Chapitre 11: Expression Lambda et Référence de méthode en Java
Chapitre 11: Expression Lambda et Référence de méthode en JavaChapitre 11: Expression Lambda et Référence de méthode en Java
Chapitre 11: Expression Lambda et Référence de méthode en Java
 
Chapitre4: Pointeurs et références
Chapitre4: Pointeurs et références Chapitre4: Pointeurs et références
Chapitre4: Pointeurs et références
 
Chap1V2019: Cours en C++
Chap1V2019: Cours en C++Chap1V2019: Cours en C++
Chap1V2019: Cours en C++
 
C# langage & syntaxe
C#   langage & syntaxeC#   langage & syntaxe
C# langage & syntaxe
 
C4 fonctions
C4 fonctionsC4 fonctions
C4 fonctions
 
Exercices en langage c
Exercices en langage cExercices en langage c
Exercices en langage c
 
Chapitre 04 : les fonctions
Chapitre 04 : les fonctionsChapitre 04 : les fonctions
Chapitre 04 : les fonctions
 
C1 - Langage C - ISIMA - Première partie
C1 - Langage C - ISIMA - Première partieC1 - Langage C - ISIMA - Première partie
C1 - Langage C - ISIMA - Première partie
 
Cours structures des données (langage c)
Cours structures des données (langage c)Cours structures des données (langage c)
Cours structures des données (langage c)
 
Langage C
Langage  CLangage  C
Langage C
 
Chapitre2 prog dsplf3
Chapitre2 prog dsplf3Chapitre2 prog dsplf3
Chapitre2 prog dsplf3
 
langage C++
langage C++langage C++
langage C++
 
Tp1 compte rendu en langage c
Tp1 compte rendu en langage cTp1 compte rendu en langage c
Tp1 compte rendu en langage c
 
Memo java
Memo javaMemo java
Memo java
 

Ähnlich wie C++ Metaprogramming : multidimensional typelist

Boosted Java to Native Interface (JNI)
Boosted Java to Native Interface (JNI)Boosted Java to Native Interface (JNI)
Boosted Java to Native Interface (JNI)Innobec
 
Découvrez C# 4.0 et les améliorations apportées à la BCL
Découvrez C# 4.0 et les améliorations apportées à la BCLDécouvrez C# 4.0 et les améliorations apportées à la BCL
Découvrez C# 4.0 et les améliorations apportées à la BCLDotNetHub
 
Visual Studio 2008 Overview
Visual Studio 2008 OverviewVisual Studio 2008 Overview
Visual Studio 2008 OverviewGregory Renard
 
Chp6 - De UML vers C++
Chp6 - De UML vers C++Chp6 - De UML vers C++
Chp6 - De UML vers C++Lilia Sfaxi
 
Memojava 100604104941-phpapp02
Memojava 100604104941-phpapp02Memojava 100604104941-phpapp02
Memojava 100604104941-phpapp02Rahma Boufalgha
 
Interception de signal avec dump de la pile d'appel
Interception de signal avec dump de la pile d'appelInterception de signal avec dump de la pile d'appel
Interception de signal avec dump de la pile d'appelThierry Gayet
 
Design Pattern introduction
Design Pattern introductionDesign Pattern introduction
Design Pattern introductionneuros
 
Chap 2--POO avec JAVA.pdf
Chap 2--POO avec JAVA.pdfChap 2--POO avec JAVA.pdf
Chap 2--POO avec JAVA.pdframadanmahdi
 
Cours c#
Cours c#Cours c#
Cours c#zan
 
IMPLEMENTATION EN PYTHON DES CONVENTIONS ALGORITHMIQUES (2022-2023)
IMPLEMENTATION EN PYTHON DES CONVENTIONS ALGORITHMIQUES  (2022-2023)IMPLEMENTATION EN PYTHON DES CONVENTIONS ALGORITHMIQUES  (2022-2023)
IMPLEMENTATION EN PYTHON DES CONVENTIONS ALGORITHMIQUES (2022-2023)Tunisie collège
 

Ähnlich wie C++ Metaprogramming : multidimensional typelist (20)

Boosted Java to Native Interface (JNI)
Boosted Java to Native Interface (JNI)Boosted Java to Native Interface (JNI)
Boosted Java to Native Interface (JNI)
 
Découvrez C# 4.0 et les améliorations apportées à la BCL
Découvrez C# 4.0 et les améliorations apportées à la BCLDécouvrez C# 4.0 et les améliorations apportées à la BCL
Découvrez C# 4.0 et les améliorations apportées à la BCL
 
Visual Studio 2008 Overview
Visual Studio 2008 OverviewVisual Studio 2008 Overview
Visual Studio 2008 Overview
 
generation_code.pdf
generation_code.pdfgeneration_code.pdf
generation_code.pdf
 
Vs2008 Linq
Vs2008 LinqVs2008 Linq
Vs2008 Linq
 
Chp6 - De UML vers C++
Chp6 - De UML vers C++Chp6 - De UML vers C++
Chp6 - De UML vers C++
 
POO-chapitre3.pptx
POO-chapitre3.pptxPOO-chapitre3.pptx
POO-chapitre3.pptx
 
C++11
C++11C++11
C++11
 
De Java à .NET
De Java à .NETDe Java à .NET
De Java à .NET
 
Memojava 100604104941-phpapp02
Memojava 100604104941-phpapp02Memojava 100604104941-phpapp02
Memojava 100604104941-phpapp02
 
Ch10
Ch10Ch10
Ch10
 
C++ 11/14
C++ 11/14C++ 11/14
C++ 11/14
 
Interception de signal avec dump de la pile d'appel
Interception de signal avec dump de la pile d'appelInterception de signal avec dump de la pile d'appel
Interception de signal avec dump de la pile d'appel
 
Design Pattern introduction
Design Pattern introductionDesign Pattern introduction
Design Pattern introduction
 
Linq Tech Days08 Lux
Linq Tech Days08 LuxLinq Tech Days08 Lux
Linq Tech Days08 Lux
 
Part1
Part1Part1
Part1
 
Chap 2--POO avec JAVA.pdf
Chap 2--POO avec JAVA.pdfChap 2--POO avec JAVA.pdf
Chap 2--POO avec JAVA.pdf
 
Cours c#
Cours c#Cours c#
Cours c#
 
Corrige tp java
Corrige tp javaCorrige tp java
Corrige tp java
 
IMPLEMENTATION EN PYTHON DES CONVENTIONS ALGORITHMIQUES (2022-2023)
IMPLEMENTATION EN PYTHON DES CONVENTIONS ALGORITHMIQUES  (2022-2023)IMPLEMENTATION EN PYTHON DES CONVENTIONS ALGORITHMIQUES  (2022-2023)
IMPLEMENTATION EN PYTHON DES CONVENTIONS ALGORITHMIQUES (2022-2023)
 

C++ Metaprogramming : multidimensional typelist

  • 1. MetaProgrammation C++ type list multidimmensionnelle Vincent Agnus, Institut de Recherche contre les Cancers de l'Appareil Digestif Developer Forum 4 18 septembre 2008 Strasbourg University of Strasbourg, France
  • 2.
  • 3. Présentation  MetaProgrammation C++  Typelist & Dispatcher  Discussion Vincent Agnus 3/50
  • 4. Meta Programmation C++  Meta Programmation = « génération par le compilateur d'algorithmes dans le code source »  Language compilé : C++, Curl, D, Eiffel, Haskell, ML and XL.  Language interprété : modifiable pdt runtime  C++ MetaProgrammation : basée sur les templates Vincent Agnus 4/50
  • 5. Meta Programmation C++ Template  Permet de définir des fonctions génériques --> comportement commun #include <iostream> template <typename T> inline const T& maximum(const T& x,const T& y) { if(y > x) return y; else return x; } int main(void) { // template instanciation std::cout << maximum<int>(3,7) << endl; //outputs 7 std::cout << maximum(3, 7) << endl; //same as above std::cout << maximum(3.2,7.3) << endl; //outputs 7.3 return 0; } Vincent Agnus 5/50
  • 6. Template C++  Spécialisation de templates --> comportement particulier #include <iostream> #include <string> template<> inline const std::string& maximum(const std::string& x,const std::string& y) { if( y.size() > x.size() ) return y; else return x; } int main(void) { std::cout << maximum<int>(3,7) << endl; //sortie 7 std::string s1(''court''); std::string s2(''trestreslong''); std::cout << maximum(s1, s2) << endl; // sortie trestreslong return 0; } Vincent Agnus 6/50
  • 7. Meta Programmation C++ Template  Classe gérant des types/valeurs génériques template<typename T> class MyVector { ... protected : int m_nbElements; T *m_elements; }; template<typename T, int N> // ici un template du genre valeur class MyArray { ... protected : T[N] m_elements; }; Vincent Agnus 7/50
  • 8. Meta Programmation C++ Template  Les templates lors de la compilation génèrent du code temporaire qui est inséré dans le code source qui est recompilé  Metaprogrammation à partir des templates  Génération de classes à la compilation  Optimisation de code à la compilation  Définition de nouveaux idioms Vincent Agnus 8/50
  • 9. Meta Programmation C++ Template  Génération de classe int factoriel(int n) { return (n==0?1:n*factoriel(n-1)); } void foo() { // 4 est connu au moment de la compilation int y = factoriel(4); // valeur calculée à chaque l'exécution !!! } Vincent Agnus 9/50
  • 10. Meta Programmation C++ Template  Génération de classe template <int N> struct Factoriel { enum { value = N * Factoriel<N - 1>::value }; }; template <> struct Factoriel<0> { enum { value = 1 }; }; int factoriel(int n) { return (n==0?1:n*factoriel(n-1)); } void foo() { int x = Factoriel<4>::value; //== 24 constante générée lors de la compilation int y = factoriel(4); // valeur calculée lors de l'exécution } Vincent Agnus 10/50
  • 11. Meta Programmation C++ Template  Optimisation de Code template<class T, int N> class MyArray { typedef MyArray<T,N> Self; Self &operator+=(const Self& rhs) { for (int i = 0; i < N; ++i) { m_elements[i] += rhs.value[i]; } // N connu => boucle déroulable return *this; } protected : T[N] m_elements; };  Compilatation : myArrayInstance += myArrayInstance2;  N connu lors de la compilation  le compilateur peut dérouler la boucle  Créer du code parallélisable Vincent Agnus 11/50
  • 12. Meta Programmation C++ Template  Créer des idioms  Exemple «Polymorphisme statique» ou «Curiously Recurring Template Pattern» template <typename DERIVED> struct base { // ... }; struct derived : base<derived> { // ... };  Objectif :  Ajout de fonctionnalités à une classe  Dérivation sans utilisation de table de virtualité Vincent Agnus 12/50
  • 13. Meta Programmation C++ Template  Curiously Recurring Template Pattern--Polymorphisme statique template <class DERIVED> struct Base { void interface() { // ... static_cast<DERIVED*>(this)->implementation(); // ... } static void static_func() { // ... Derived::static_sub_func(); // ... } }; struct Derived : Base<Derived> { void implementation(); static void static_sub_func(); }; Vincent Agnus 13/50
  • 14. Meta Programmation C++ Template  Curiously Recurring Template Pattern-- exemple 1 template <typename T> struct counter class X : counter<X> { { counter() // ... { }; objects_created++; objects_alive++; class Y : counter<Y> } { // ... virtual ~counter() }; { --objects_alive; } static int objects_created; static int objects_alive; }; template <typename T> int counter<T>::objects_created( 0 ); template <typename T> int counter<T>::objects_alive( 0 ); Vincent Agnus 14/50
  • 15. Meta Programmation C++ Template  Curiously Recurring Template Pattern -- Exemple 2 // A class template to express an equality comparison interface. template<typename T> class equal_comparable { friend bool operator==(T const &a, T const &b) { return a.equal_to(b); } friend bool operator!=(T const &a, T const &b) { return !a.equal_to(b); } }; class value_type // Class value_type wants to have == and !=, so it derives from // equal_comparable with itself as argument (which is the CRTP). : private equal_comparable<value_type> { public: bool equal_to(value_type const& rhs) const; // to be defined }; Vincent Agnus 15/50
  • 16. MetaProgrammation C++  Avantages – Inconvénients :  Générique  Temps compilation – Performance lors runtime  Maintenance  Portabilité • Différent compilateurs  Lisibilité : • syntaxe • message d'erreurs  Bibliothèque C++ : boost meta programming Language http://www.boost.org/doc/libs/release/libs/mpl/ Vincent Agnus 16/50
  • 17. Type List & Dispatcher Vincent Agnus 17/50
  • 18. Type List & Dispatcher  Objectif : Automatisation écriture de code pour la gestion de plusieurs types/classes  Exemples  problématique IRCAD  Principe de la solution mise en place  Détail de l'implémentation  Discussion Vincent Agnus 18/50
  • 19. Type List & Dispatcher Motivation  class Shape {...}; class Point : public Shape {...}; Exemple une Fabrique class Ball : public Shape {...}; template<T> T *create() { return new T; } class TrivialShapeFactory { static Shape *build(std::string &key) { if ( key == "Point" ) { return create<Point>(); } else if ( key == "Ball" ) { return create<Ball>(); } } }; Vincent Agnus 19/50
  • 20. Type List & Dispatcher Motivation  Plus de degrés de liberté class Shape {...}; class Point : public Shape {...}; class Ball : public Shape {...}; class Color {...}; class Red : public Color {...}; class Green : public Color {...}; class Blue : public Color {...}; template< class COLOR, class SHAPE > class ColoredShape : public SHAPE { // .... COLOR m_color; }; template< COLOR, SHAPE> Shape *createColoredShape() { return new ColoredShape< COLOR , SHAPE >; } Vincent Agnus 20/50
  • 21. Type List & Dispatcher Motivation  La nouvelle fabrique à 2 degrés de liberté class ColoredShapeFactory { static Shape *build(std::string &color, std::string &shape) { if ( shape == "Point" ) { if ( color == "Red" ) { return createColoredShape<Red, Point>();} if ( color == "Green") { return createColoredShape<Green, Point>();} if ( color == "Blue" ) { return createColoredShape<Blue, Point>();} } else if ( shape == "Ball" ) { if ( color == "Red" ) { return createColoredShape<Red, Ball>();} // and so on ... } ... } };  Ajout d'une nouvelle classe -> risque d'erreurs  Typelist --> automatisation Vincent Agnus 21/50
  • 22. Type List & Dispatcher Motivation  Motivation « IRCAD »  Utilisation de la librairie template ITK  template <typename PIXELTYPE, int DIM> itk::Image<PIXELTYPE,DIM>  template <typename TImageIn, typename TImageOut> itk::ImageFilter<TImageIn,TImageOut>  Nous utilisons des types images non templates (conversion <-> ITK )  void *m_buffer;  PixelType m_pixelType;  Il faut gérer les entrées/sorties des filtres avec des images de différents types Vincent Agnus 22/50
  • 23. Type List & Dispatcher Mise en Oeuvre  Automatisation l'écriture du code  MetaProgrammation C++ :  Typelist : définir la liste des types à traiter  Le Dispatcher qui va parcourrir cette liste  Mapping entre Type de la typelist et Type requis lors du runtime  Functor (traitement)  Gestion des type list n-dimensionnelles  Cas d'utilisation : Dispatcher sur Fabriques Vincent Agnus 23/50
  • 24. Type List & Dispatcher définition d'une type list  Type List = « Un container qui contient des types »  La boost MPL fournit plusieurs type de typelist #include<vector> #include<boost/mpl/vector.hpp> #include<boost/mpl/at.hpp> void f() { std::vector<int> classicContainer(10); int i = classicContainer.at(1); typedef boost::mpl::vector< char , std::string, int > TypeList; typedef boost::mpl::at_c< TypeList, 1 >::type StringType; StringType v = ''toto''; // OK ! } Vincent Agnus 24/50
  • 25. Type List & Dispatcher Cas d'utilisation  Dispatcher & Fabrique a 1 degré de liberté #include <boost/mpl/vector.hpp> // used to define type list #include <Dispatcher.hpp> // define our dispatcher struct ShapeFactory { static Shape *build(std::string key) {/ // type list of supported types typedef boost::mpl::vector<Point,Ball> GeneratedShapeTypeList; Shape *shape=NULL; Dispatcher< GeneratedShapeTypeList, ShapeGenerator >::invoke(key,shape); return shape; } }; Vincent Agnus 25/50
  • 26. Type List & Dispatcher Cas d'utilisation  Dispatcher & Fabrique a 1 degré de liberté #include <boost/mpl/vector.hpp> // used to define type list #include <Dispatcher.hpp> // define our dispatcher struct ShapeGenerator { template<class T> void operator()(Shape * &t) // we use a reference on a pointer to modify it { t=new T; } }; // Correspondance valeur clef <--> type ( fonction IsMapping ) // exemple chaine ''Point'' avec le type Point struct ShapeFactory { static Shape *build(std::string key) {/ // type list of supported types typedef boost::mpl::vector<Point,Ball> GeneratedShapeTypeList; Shape *shape=NULL; Dispatcher< GeneratedShapeTypeList, ShapeGenerator >::invoke(key,shape); return shape; } }; Vincent Agnus 26/50
  • 27. Type List & Dispatcher Cas d'utilisation  Correspondance valeur clef <--> Type #include <TypeMapping.hpp> // used to define binding between key value and concrete type // define template isMapping function //template<typename TYPE,KEYTYPE> //bool isMapping<TYPE>(const KEYTYPE &key) //{ // // mandatory template specialization requested // // missing binding declaration involve compilation fail //} template<> bool isMapping<Point>(const std::string &key) { return key == "Point"; } template<> bool isMapping<Ball>(const std::string &key) { return key == "Ball"; } Vincent Agnus 27/50
  • 28. Type List & Dispatcher Cas d'utilisation  Code Généré Compilation de Dispatcher< GeneratedShapeTypeList, ShapeGenerator >::invoke(key,shape);  Ps e u d o Co d e Gé n é ré { // generated at compile time if ( isMapping< Point , std::string >(key) ) { ShapeGenerator shapeGenerator; shapeGenerator.operator<Point>( shape ); } else if ( isMapping< Ball , std::string >(key) ) { ShapeGenerator shapeGenerator; shapeGenerator.operator<Ball>( shape ); } ... // same for each type stored in GeneratedShapeTypeList } Vincent Agnus 28/50
  • 29. Type List & Dispatcher Cas d'utilisation  API du Dispatcher  Généricité vis à vis  Nature clef  Functor  Type du container de la TypeList // file Dispatcher.hpp template<class MANAGEDTYPELIST, class FUNCTOR> class Dispatcher { static void invoke(); template<class KEYTYPE> static invoke(const KEYTYPE &key); template<class KEYTYPE,class PARAMETER> static invoke(const KEYTYPE &key, PARAMETER &param); }; Vincent Agnus 29/50
  • 30. Type List & Dispatcher Cas d'utilisation  Dispatcher & Fabrique a 2 degrés de liberté #include <Combinatory.hpp> // contain our meta-function cartesianProduct // isMapping specialized for Colors // isMapping for Combinaisont Type auto managed // functor ColoredShapeGenerator; struct ColoredShapeFactory { static Shape *build(std::string shape, std::string color) { //define two type lists for shape and color typedef boost::mpl::vector< Point, Ball >::type ManagedShape; typedef boost::mpl::vector< Red, Green, Blue >::type ManagedColor; // create the 2-dimensional typelist typedef boost::mpl::vector< ManagedShape, ManagedColor >::type MultiDimList; // generate mono-dimensional typelist with element of size 2 (shape,color) typedef boost::mpl::apply< CartesianProduct, MultiDimList>::type CombinaisonList; Shape *coloredShape=NULL; // generate the multi-key std::list< std::string > key; key.push_back(shape);key.push_back(color); Dispatcher< CombinaisonList , ColoredShapeGenerator >::invoke(key,coloredShape); return coloredShape; } }; Vincent Agnus 30/50
  • 31. Type List & Dispatcher Cas d'utilisation  Dispatcher & Fabrique a 2 degrés de liberté  Appel du Functor ColoredShapeGenerator Dispatcher< CombinaisonList , ColoredShapeGenerator >::invoke(key,coloredShape); struct ColoredShapeGenerator { template<class TYPESEQUENCE> // paire (SHAPE,COLOR) void operator()(Shape * &t) { // insure is a TSEQUENCE BOOST_STATIC_ASSERT ( boost::mpl::is_sequence<TYPESEQUENCE>::value ); // retreive each type in 2 sized element TYPESEQUENCE typedef typename boost::mpl::at_c<TYPESEQUENCE,0>::type ChoosenShape; typedef typename boost::mpl::at_c<TYPESEQUENCE,1>::type ChoosenColor; t=new ColoredShape< ChoosenShape, ChoosenColor> ; } }; Vincent Agnus 31/50
  • 32. Type List & Dispatcher Cas d'utilisation  Fabrique a 2 degrés de liberté  Mix des 2 types list : CombinaisonList struct ColoredShapeFactory { static Shape *build(std::string shape, std::string color) { //define two type list for shape and color typedef boost::mpl::vector< Point, Ball >::type ManagedShape; typedef boost::mpl::vector< Red, Green, Blue >::type ManagedColor; // create the 2-dimensional typelist typedef boost::mpl::vector< ManagedShape, ManagedColor >::type MultiDimList; // generate mono-dimensional typelist with element of size 2 (shape,color) typedef boost::mpl::apply< CartesianProduct, MultiDimList>::type CombinaisonList; Shape *coloredShape=NULL; // generate the multi-key std::list< std::string > key; key.push_back(shape);key.push_back(color); Dispatcher< CombinaisonList , ColoredShapeGenerator >::invoke(key,coloredShape); return coloredShape; } }; Vincent Agnus 32/50
  • 33. Type List & Dispatcher Cas d'utilisation  Implémentation utilisant la boost::mpl  Fonction Produit Cartésien : génère les combinaisons (ordonnées) de plusieurs ensembles  Produit Cartésien de n ensembles de taille si donne un ensemble de s1⋯sn n-uplets  Exemple :   t 1,1 t 3,1 t 1,3 t  TL1= t 1,2 , TL2= 2,1 , TL3= t 3,2 t 2,2 t 3,3   t 1,1 , t 2,1 , t 3,1 , t 1,1 , t 2,1 , t 3,2  , t 1,1 ,t 2,1 ,t 3,3  , TL1⊗TL2⊗TL3 = t 1,1 , t 2,2 , t 3,1 , t 1,1 , t 2,2 , t 3,2  , t 1,1 ,t 2,2 ,t 3,3  , ⋮ ⋮ ⋮ t 1,3 , t 2,2 ,t 3,1 , t 1,3 , t 2,2 , t 3,2 , t 1,3 ,t 2,2 ,t 3,3  Vincent Agnus 33/50
  • 34. Type List & Dispatcher Cas d'utilisation  Génération des combinaisons de typelist :  ManagedShape ~ mpl::vector<Point,Ball>  ManagedColor ~ mpl::vector<Red,Green,Bue>  MultiDimList mpl::vector< mpl::vector<Point,Ball> mpl::vector<Red,Green,Bue> >  Appel Meta Fonction Produit Cartesien typedef boost::mpl::apply< CartesianProduct, MultiDimList>::type CombinaisonList;  Génération à la compilation de : typedef boost::mpl::vector< boost::mpl::vector<Point, Red>, boost::mpl::vector<Point, Green>, boost::mpl::vector<Point, Blue>, boost::mpl::vector<Ball , Red>, boost::mpl::vector<Ball , Green, boost::mpl::vector<Ball , Blue> >::type CombinaisonList Vincent Agnus 34/50
  • 35. Type List & Dispatcher Cas d'utilisation  Dispatcher Fabrique a 3 degrés de liberté et + : Modification mineure du code ( couleurs ) struct ColoredShapeFactory { static Shape *build(std::string shape, std::string color, std::string style) { //define two type list for shape and color typedef boost::mpl::vector< Point, Ball >::type ManagedShape; typedef boost::mpl::vector< Red, Green, Blue >::type ManagedColor; typedef boost::mpl::vector< Plain, WireFrame, Hidden >::type ManagedStyle; // create the 2-dimensional typelist typedef boost::mpl::vector< ManagedShape, ManagedColor , ManagedStyle>::type MultiDimList; // generate mono-dimensional typelist with element of size 3 (shape,color,style) typedef boost::mpl::apply< CartesianProduct, MultiDimList>::type CombinaisonList; Shape *newShape=NULL; // generate the multi-key std::list< std::string > key; key.push_back(shape);key.push_back(color); key.push_back(style); Dispatcher< CombinaisonList , 3DOFShapeGenerator >::invoke(key,newShape); return newShape; } }; Vincent Agnus 35/50
  • 36. Type List & Dispatcher Détail  Détail d'implémentation  Dispatcher : méthod invoke  IsMapping n-D ( auto géré )  CartesianProduct Meta Function Vincent Agnus 36/50
  • 37. Type List & Dispatcher Détail  Dispatcher : méthod invoke  Pour chaque type dans la typelist  Test si type et clef compatible isMapping  Si OK Appel functor template< class TYPELIST, class FUNCTOR > class Dispatcher { template< class KeyType, class Parameter > static void invoke( const KeyType &keytype, Parameter &param ); }; Vincent Agnus 37/50
  • 38. Type List & Dispatcher Détail template< class TYPELIST, class FUNCTOR > class Dispatcher { template< class KeyType, class Parameter > static void invoke( const KeyType &keytype, Parameter &param ) { namespace mpl = boost::mpl; typedef typename mpl::pop_front<TYPELIST>::type Tail; typedef typename mpl::front<TYPELIST>::type Head; if ( isMapping<Head>(keytype) ) { // create the functor then excute it FUNCTOR f; f.template operator()<Head>(param); } else { // compile time : recursively call other element in the list typedef typename mpl::eval_if< mpl::empty<Tail>, mpl::identity< EmptyTypeListAction >, mpl::identity< Dispatcher<Tail,FUNCTOR > > >::type typex; typex::invoke(keytype,param); } } Vincent Agnus 38/50
  • 39. Type List & Dispatcher Détail  Compilation de Dispatcher<ManagedShape,GeneratorFuncor>::invoke(key,shape) typedef mpl::vector<Point,Ball> ManagedShape; Dispatcher<ManagedShape, GenFunctor>::invoke( key, shape) { if( isMapping<Point>(key) ) { GenFunctor().operator<Point>()(shape); } else { typedef Dispatcher< mpl::vector<Ball>, GenFunctor> typex; typex::invoke(key,shape); } } Dispatcher< mpl::vector<Ball>, GenFunctor>::invoke( key, shape) { if ( isMapping<Ball>(key) ) { ... } else { // same API than Dispatcher but always throw ''Incorrect Key'' EmptyTypeListAction::invoke(key,shape); } } Vincent Agnus 39/50
  • 40. Type List & Dispatcher Détail  Détail d'implémentation  Dispatcher : méthod invoke  IsMapping n-D ( auto géré )  CartesianProduct Meta Function Vincent Agnus 40/50
  • 41. Type List & Dispatcher Détail  IsMapping : binding Type <-> valeur clef  Robuste vis à vis oublie spécialisation -> erreur de compilation template<class TYPE,class KEY> bool isMapping<TYPE>(const KEY &key) { BOOST_STATIC_ASSERT(sizeof(TYPE) == 0) }  Gestion automatique des clefs multiple càd isMapping< mpl::vector<...> >(keys) = isMapping< mpl::front(mpl::vector<...>) >(keys.front()) && isMapping< mpl::pop_front(mpl::vector<...>) >(keys.pop_front()); Vincent Agnus 41/50
  • 42. Type List & Dispatcher Détail  Détail d'implémentation  Dispatcher : méthod invoke  IsMapping n-D ( auto géré )  CartesianProduct Meta Function Vincent Agnus 42/50
  • 43. Type List & Dispatcher Détail  Produit cartésien est défini comme une meta fonction MPL : (équivalent functor C++) struct MaMetaFunction { template<class PARAM1, class PARAM2, ...> struct apply { typedef .... type; }; };  Appel boost::mpl::apply<MetaFct,P1,...>::type est un typedef sur MetaFct::apply<P1,...>::type  exemple boost::mpl::identity Vincent Agnus 43/50
  • 44. Type List & Dispatcher Détail  Produit Cartésien :  Prop TL1  TL2  ...  TLn = TL1  ( TL1  (...  TLn ))) struct CartesianProduct { template< class MultiSet > struct apply { typedef typename boost::mpl::reverse_fold< MultiSet, boost::mpl::vector<>, boost::mpl::apply2< CartesianProduct_1_N_Recurser, boost::mpl::_2, boost::mpl::_1 > >::type type; }; };  3 meta fonctions intermédiaires  Au total 45 lignes Vincent Agnus 44/50
  • 45. Type List & Dispatcher Discussion  Discussion  Généricité vis à vis clef  Spécificité de notre approche  Retour d'expériences Vincent Agnus 45/50
  • 46. Type List & Dispatcher Discussion  Généricité vis à vis des clefs  Dimension des images : utilisation de namespace boost { namespace mpl { template< int N > struct int_ { ... }:  Gestion des Multi-méthodes : • Clef spéciale : struct TypeInfo { std::type_info *m_data}; • Spécialisation : template<> bool isMapping<Point>(const TypeInfo &key) { return *key.m_data == typeid(Point); } Vincent Agnus 46/50
  • 47. Type List & Dispatcher Discussion  Spécificité de notre approche  Gestion native des types lists multidimensionnelles  Externalisation de la combinaison des type lists  Statique  Recherche clef type en O(n) Vincent Agnus 47/50
  • 48. Type List & Dispatcher Discussion  Retour d'expériences  MPL : • Documentation web : boost mpl réduite • Debuggeage à la compilation par STATIC_ASSERT • Multi OS ( Linux, OsX, win32 ) OK • paradigme programmation fonctionnelle  MetaProgrammation C++ • Message erreur de compilation « illisible » • Généricité • Code Utilisateur : simplifié & sécurisé Vincent Agnus 48/50
  • 49. Type List & Dispatcher Ressources  Livres :  Modern C++ Design, A. Alexandrescu. « C++ in depth series»  C++ Template Metaprogramming, D. Abrahams, A. Gurtovoy. « C++ in depth series»  C++ Templates - The Complete Guide, D. Vandevoorde et N. Josuttis. Addison-Wesley  Article :  En cours rédaction : « Multi-Dimensional C++ Type List » pour revue « Computer Languages, Systems & Structures » Ed. Elsevier  Distribution des sources ? Vincent Agnus 49/50
  • 50. Merci pour votre attention Vincent Agnus 50/50