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 :

« Super » macro variadique


Sujet :

Langage C++

  1. #1
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut « Super » macro variadique
    Bonjour tous,

    Dans mon projet, la plupart de mes « classes » sont des typedefs de templates variadiques. Ça fait du code joli et concis, jusque là tout va bien.

    Sauf que souvent ces typedefs font références les uns aux autres. Pour résoudre les problèmes de dépendances cycliques engendrés, je dois écrire des pimpl. Et l'interface est plutôt lourde à reproduire…
    Par exemple, alors qu'un typedef donnerait ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    typedef
    	alternative_node
    	<
    		simple_declaration,
    		asm_definition,
    		namespace_alias_definition,
    		using_declaration,
    		using_directive
    	>
    	block_declaration
    ;
    … je dois remplacer le code ci-dessus par celui-ci, pour mettre en place le pimpl (ne vous souciez pas du sens de ce code, ce n'est pas le sujet) :
    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
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
     
    /*certains des types présents dans ce typedef sont incomplets*/
    typedef
    	alternative_node
    	<
    		simple_declaration,
    		asm_definition,
    		namespace_alias_definition,
    		using_declaration,
    		using_directive
    	>
    	block_declaration_t
    ;
     
    typedef
    	alternative_node
    	<
    		asm_definition,
    		namespace_alias_definition,
    		using_declaration,
    		using_directive
    	>
    	block_declaration_tail_t
    ;
     
    class block_declaration: public composite_node
    {
    	public:
    		typedef block_declaration_t type;
    		typedef simple_declaration head_node_t;
    		typedef block_declaration_tail_t tail_alternative_node_t;
     
    		block_declaration(simple_declaration&& o);
     
    		block_declaration(asm_definition&& o);
     
    		block_declaration(namespace_alias_definition&& o);
     
    		block_declaration(using_declaration&& o);
     
    		block_declaration(using_directive&& o);
     
    		block_declaration(const block_declaration& o);
     
    		block_declaration(block_declaration&& o);
     
    		~block_declaration();
     
    		const block_declaration&
    		operator=(const block_declaration& o);
     
    		void
    		get(boost::optional<const simple_declaration&>& node) const;
     
    		void
    		get(boost::optional<const asm_definition&>& node) const;
     
    		void
    		get(boost::optional<const namespace_alias_definition&>& node) const;
     
    		void
    		get(boost::optional<const using_declaration&>& node) const;
     
    		void
    		get(boost::optional<const using_directive&>& node) const;
     
    	private:
    		std::unique_ptr<type> impl_;
    };
    Comme vous le voyez, c'est un tantinet verbeux. Et encore, je n'ai pas mis les définitions des fonctions membres.

    Voici donc ma question : Existe-t-il une technique de métaprogrammation (certainement à base de macros) qui me permettrait de factoriser le code ci-dessus par quelque chose comme celui-ci ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    ALTERNATIVE_NODE_PIMPL
    (
    	block_declaration,
    	simple_declaration,
    	asm_definition,
    	namespace_alias_definition,
    	using_declaration,
    	using_directive
    )
    Même si le nombre d'arguments doit être spécifié, je prends aussi !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    ALTERNATIVE_NODE_PIMPL5
    (
    	block_declaration,
    	simple_declaration,
    	asm_definition,
    	namespace_alias_definition,
    	using_declaration,
    	using_directive
    )
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  2. #2
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Tu veux dire les macros variadiques ?
    Comme dans:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    #define  LOG_DEBUG(...)        getLogger()->Log(Level.DEBUG,_VA_ARGS_)
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  3. #3
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    Apparemment, les macros variadiques au sens C99 ne sont pas suffisantes pour mon cas, même si j'ai déjà un début de solution qui en tire parti :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #define SCALPEL_ALTERNATIVE_NODE_PIMPL_TYPE_TYPEDEF_BEGIN\
    typedef\
    	alternative_node\
    	<
     
    #define SCALPEL_ALTERNATIVE_NODE_PIMPL_TYPE_TYPEDEF_END\
    	>\
    	type\
    ;
     
    #define SCALPEL_ALTERNATIVE_NODE_PIMPL_TYPE_TYPEDEF(...)
    SCALPEL_ALTERNATIVE_NODE_PIMPL_TYPE_TYPEDEF_BEGIN\
    	_VA_ARGS_\
    SCALPEL_ALTERNATIVE_NODE_PIMPL_TYPE_TYPEDEF_END
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Tu as regardé du côté de boost::pp : http://www.boost.org/doc/libs/1_39_0...doc/index.html
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    Argh, j'avais fouillé du côté de Boost.MPL, mais PP, je ne connaissais pas. Je sens que ça va m'intéresser

    Merci beaucoup Loïc !
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  6. #6
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Hum ça me parait trop facile mais bon : pourquoi ne pas faire... :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // Je met <...> pour ne pas avoir à recopier toute la liste des arguments du template
    class block_declaration : public alternative_node<...>
    {
    public :
     
        // Avec eventuellement (si tu as besoin de faire la conversion entre le type template et ton "typedef") :
        block_declaration() {}
        block_declaration(const alternative_node<...>& obj) : alternative_node<...>(obj) {}
    };
    Ca marche très bien chez moi.

  7. #7
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    Eh non, on ne peut hériter d'un type incomplet (incomplet == dont on n'a qu'une forward declaration) ! Sinon le typedef aurait fait l'affaire.
    Edit : Ici, le template alternative_node est complet. C'est l'un des types arguments du template qui est incomplet, rendant donc l'instance du template elle-même incomplète.

    De plus, ça n'aurait de toutes façons pas été très propre, puisque la classe alternative_node n'est pas conçue pour être héritée (pas de destructeur virtuel, pas abstrait, …).

    Je précise que la piste boost.pp était bien la bonne
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  8. #8
    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
    T'as utilisé pp comment pour résoudre ton problème au final? (ça m'intéresse et jvois pas trop)
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  9. #9
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    J'ai utilisé les séquences :
    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
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    #define SCALPEL_ALTERNATIVE_NODE_PIMPL_DECLARATION_CONSTRUCTOR(r, alternative_node_type, type) \
    alternative_node_type(type&& o);
     
    #define SCALPEL_ALTERNATIVE_NODE_PIMPL_DECLARATION_GET_FUNCTION(r, x, type) \
    void                                           \
    get(boost::optional<const type&>& node) const; \
     
    #define SCALPEL_ALTERNATIVE_NODE_PIMPL_DECLARATION(alternative_node_type, type_seq) \
    class alternative_node_type: public node                                            \
    {                                                                                   \
    	public:                                                                         \
    		typedef                                                                     \
    			alternative_node                                                        \
    			<                                                                       \
    				BOOST_PP_SEQ_ENUM(type_seq)                                         \
    			>                                                                       \
    			type                                                                    \
    		;                                                                           \
    		typedef BOOST_PP_SEQ_HEAD(type_seq) head_node_t;                            \
    		typedef                                                                     \
    			alternative_node                                                        \
    			<                                                                       \
    				BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TAIL(type_seq))                      \
    			>                                                                       \
    			tail_alternative_node_t                                                 \
    		;                                                                           \
                                                                                        \
    		BOOST_PP_SEQ_FOR_EACH                                                       \
    		(                                                                           \
    			SCALPEL_ALTERNATIVE_NODE_PIMPL_DECLARATION_CONSTRUCTOR,                 \
    			alternative_node_type,                                                  \
    			type_seq                                                                \
    		)                                                                           \
                                                                                        \
    		alternative_node_type(const alternative_node_type& o);                      \
                                                                                        \
    		alternative_node_type(alternative_node_type&& o);                           \
                                                                                        \
    		~alternative_node_type();                                                   \
                                                                                        \
    		const alternative_node_type&                                                \
    		operator=(const alternative_node_type& o);                                  \
                                                                                        \
    		child_const_iterator_range                                                  \
    		children() const;                                                           \
                                                                                        \
    		BOOST_PP_SEQ_FOR_EACH                                                       \
    		(                                                                           \
    			SCALPEL_ALTERNATIVE_NODE_PIMPL_DECLARATION_GET_FUNCTION,                \
    			~,                                                                      \
    			type_seq                                                                \
    		)                                                                           \
                                                                                        \
    	private:                                                                        \
    		std::unique_ptr<type> impl_;                                                \
    };
    L'appel à la fonction donne cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SCALPEL_ALTERNATIVE_NODE_PIMPL_DECLARATION
    (
    	block_declaration,
    	(simple_declaration)
    	(asm_definition)
    	(namespace_alias_definition)
    	(using_declaration)
    	(using_directive)
    )
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  10. #10
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Au temps pour moi, j'avais confondu la situation
    J'utilise cette méthode quand je veux faire des "typedef template" (avec une classe T inconnue).

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

Discussions similaires

  1. Super Macro
    Par khayyam90 dans le forum Téléchargements
    Réponses: 1
    Dernier message: 01/12/2012, 17h01
  2. problème dans super macro
    Par younes.developpeur dans le forum Imagerie
    Réponses: 0
    Dernier message: 07/07/2011, 16h05
  3. macro super compliquée
    Par miopie dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 14/06/2010, 21h16
  4. Réponses: 3
    Dernier message: 01/10/2006, 13h04
  5. Réponses: 2
    Dernier message: 22/07/2002, 12h13

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