Comment définir une macro qui définit une fonction qui s'appelle elle-même?
Je veux faire une macro qui permet de définir une fonction qui appelle cette fonction sur une liste d'objets. Il ne doit pas nécessairement être un pré-processeur de macro, mais il devrait fonctionner.
Je veux écrire quelque chose comme ceci:
CALL_ON_ALL(doSomething(int arg1, bool arg2))
Et je veux qu'il à le produire:
void doSomething(int arg1, bool arg2) {
for (int i = 0; i < delegates.size(); i++)
delegates[i]->doSomething(arg1, arg2);
}
J'ai quelque chose qui fonctionne:
#define CALL_ON_ALL(defSig, callSig) \
void defSig { \
for (int i = 0; i < delegates.size(); i++) \
delegates[i]->callSig; \
}
Le problème est que je dois écrire la définition de la signature et de l'appel de la signature séparément comme ceci:
CALL_ON_ALL(doSomething(int arg1, bool arg2), doSomething(arg1, arg2))
Est-il une meilleure façon de le faire?
MODIFIER
Il ne doit pas nécessairement être un pré-processeur de macro. Tout ce qui fonctionne le fera.
Regardez comment CxxTest-t-il pour les objets fantaisie.
Yep, mais je doute qu'il peut être aidé.
Retrait
J'ai eu ce problème avant, et n'a trouvé aucune façon de la contourner. 🙁 Macros ne sont tout simplement pas assez puissant pour ce genre de chose.
Oh, variadic templates sera certainement résoudre ce! Mais... c'est pas avec des macros.
Yep, mais je doute qu'il peut être aidé.
Retrait
c
balise, puis. Aussi, veuillez utiliser @
notification de la syntaxe.J'ai eu ce problème avant, et n'a trouvé aucune façon de la contourner. 🙁 Macros ne sont tout simplement pas assez puissant pour ce genre de chose.
Oh, variadic templates sera certainement résoudre ce! Mais... c'est pas avec des macros.
OriginalL'auteur Tim Mahoney | 2013-01-05
Vous devez vous connecter pour publier un commentaire.
Essayez de faire de la signature de séparer les arguments (deux arguments):
Vous pouvez dupliquer ce pour d'autres argument des nombres.
Bon. C'est pas joli ou beau, mais il fonctionne, et ne nécessite pas la restructuration de votre code.
OriginalL'auteur Linuxios
C'est un bon exemple pour des fonctions d'ordre supérieur, qui sont des fonctions prenant une autre fonction comme argument. Dans ce cas, la fonction doit être appelée sur chaque élément.
Celui-ci définit un ordre supérieur d'appel de fonction
f
sur chaque élément. Il nécessite de C++11 pour les variadic templates (args...
). Si vous n'avez pas de C++11 est disponible, vous pouvez supprimer letypename ...Args
et de travailler avec fixe les types d'argument dans la fonction de signature.Maintenant, vous pouvez appeler à l'aide de cette syntaxe:
La
std::mem_fun
chose crée un temporaire de la fonction de l'objet pour la fonction de membre que vous souhaitez appeler pour chaque délégué. Vous pouvez également appliquer d'autres fonctions, en prenant un pointeur comme premier argument. Par exemple, cette petite fonction lambda (également que depuis C++11):qui est à peu près la même chose, juste une autre syntaxe.
Voir un exemple ici:
std::mem_fun
)Une version légèrement différente de ce code utilise une gamme de base au lieu de indexées en fonction de boucle, qui semble beaucoup plus propre (nécessite également de C++11):
Pour votre information, il y a
std::for_each
, ce qui fait à peu près ce que vous voulez, mais de manière un peu plus fonctionnel, comme il ne prend pas des paramètres de la fonction par elle-même, mais vous fournir une fonction lambda /foncteur qui prend seulement un pointeur vers une instance. Comparer le code suivant à l'un au-dessus de la fonction lambda:La seule différence est que nous avons à passer
.begin()
et.end()
itérateurs, au lieu d'une seule instance de conteneur, commedelegates
. Cependant, il y a beaucoup d'autres algorithmes définis dans la bibliothèque standard qui valent le coup d'oeil!!!Ici vous allez.
C'est bon pour en réalité appeler les fonctions des délégués, mais je ne parviens pas encore à définir les fonctions à l'aide d'une macro?
les méthodes sur le délégué doit avoir une certaine de la viande, ne devrait-elle pas ? Si vous continuez à déléguer, rien n'est jamais atteint.
Je ne pense pas que le premier argument de
42
va travailler avec un membre de pointeur de fonction.OriginalL'auteur leemes
Je pense que c'est ce que vous cherchez:
cela va générer
Vous pouvez trouver plus d'informations comment tout ce "bordel" fonctionne ici: Variadic récursive macros du préprocesseur - est-il possible?
Bien que les deux solutions sont différentes et c'est une question de celle qui vous convient le mieux. Principales œuvres pour un nombre quelconque d'arguments, mais est beaucoup plus compliqué et probablement des erreurs de la Linuxious pour seulement un nombre fixe mais est très simple.
C'est vrai. Merci pour l'aide!
OriginalL'auteur Svetlin Mladenov
Dans C, il existe variadic argument des macros, ce qui serait très pratique ici, je suppose. Ils ne sont normalement pas partie du C++ (subtile différence), bien que la plupart des compilateurs de les mettre en œuvre ne pas les limiter à C.
En C++, vous êtes mieux de toucher les modèles, en particulier avec les variadic templates en C++11 (et de transfert parfait), mais je vais essayer d'utiliser le préprocesseur, pour le plaisir et
profithum...Si nous voulons un réel C++03 préprocesseur solution, alors nous avons fait appel à Boost.Préprocesseur. Le botteur réel est le Préprocesseur de la Séquence: on peut (en théorie*) la liste des éléments qui peuvent être manipulée à volonté, ce qui nous obtient assez proche pour le confort de variadic macros.
Mais avant de nous plonger dans y, on doit remarquer que les noms des arguments sont tout à fait sans importance, et que seule leur type est vraiment important.
Je propose donc la syntaxe suivante:
Les entrailles sont un peu plus subtil, et je ne suis pas sûr de les obtenir à droite sur le premier essai, il doit probablement quelque chose comme:
Remarque: la complexité n'est pas trop terrible, il y a N appels à
BOOST_PP_SEQ_ELEM
qui est elle-même linéaire, conduisant à une équation du second degré de complexité. Je ne pouvais pas trouver unBOOST_PP_SEQ_*
macro qui pourrait énumérer les arguments et place des virgules entre eux.*Dans la pratique, il y a une démo avec près d'une centaine d'éléments dans les docs, espérons que ça suffit 😉
Eh bien... Boost est du C++ et vous êtes libre d'extraire autant, ou aussi peu, que vous le souhaitez (la licence est extrêmement permissive); ce qui est le point de réinventer la roue ?
Il est
BOOST_PP_SEQ_ENUM
qui vous permet de convertir une séquence délimitée par des virgules arguments.oui, mais il place les éléments de nu (ici les types donc) où je veux nom eux, c'est à dire je veux transformer
(int)(bool)
enint arg0, bool arg1
.OriginalL'auteur Matthieu M.
Tout d'abord, placer les parenthèses autour de votre types, de sorte que le préprocesseur peut l'analyser. Donc, vous appelez
CALL_ON_ALL
comme ceci:Voici quelques macros qui permet de récupérer le type et la bande du type(vous voulez de l'espace de noms, je suis en laissant au large de l'espace de noms juste pour la démonstration):
Ces macros fonctionnent comme cela. Lorsque vous écrivez
STRIP((int) arg1)
il sera étendu àarg1
. Et quand vous écrivezPAIR((int) arg1)
il sera étendu àint arg1
. Maintenant, vous voulez faire est d'appliquer ces macros à chaque argument qui est passé, voici donc une simpleAPPLY
macro qui vous permettra de faire jusqu'à 8 arguments:Maintenant heres comment vous pouvez écrire votre
CALL_ON_ALL
macro:Remarque: Ce ne sera probablement pas travailler dans MSVC, car ils ont un buggy de préprocesseur(bien qu'il existe des solutions de contournement).
OriginalL'auteur Paul Fultz II