Je développe une application simple événementielle dans C ++ 11 basée sur le modèle de publication / souscription. Les classes ont un ou plusieurs Voici un code très simplifié de l'idée: P> Onketvereventent () Code> Invoqué par la boucle d'événement (inversion du contrôle). Étant donné que l'application est en fait un micrologiciel, où la taille du code est critique et la flexibilité n'est pas haute priorité, la partie "Souscrire" est une table simple avec les identifiants d'événement et les gestionnaires associés.
typedef void (*Pfn)(void*, int);
Pfn pfn1 = reinterpret_cast<Pfn>(&Button::onTick);
Pfn pfn2 = reinterpret_cast<Pfn>(&Menu::onButtonPressed);
3 Réponses :
Votre 1ère idée est votre solution typique objet orientée au problème. C'est parfaitement bien, mais un peu lourd - pas aussi utile que Votre 2e idée - maintenant, il y a quelque chose que nous pouvons travailler avec! Ceci est proche de la façon dont avec ça , vous avez essentiellement Maintenant une idée puis utilisez lambdas pour faire des choses telles que: p> mais vous devez tenir sur les contextes en quelque sorte - qui ajoute un travail supplémentaire. P> p> std :: fonction code>. Votre 3ème idée est un comportement indéfini. Nope Nope Nope.
std :: fonction code> est réellement implémenté. Nous pouvons écrire une classe qui peut prendre n'importe quel objet appelable avec
int code> et renvoie
vide code>: p>
std :: Fonction
Votre suggestion encapsule élégamment un concept similaire à ce que j'avais à l'esprit (en option 2) dans un seul foncteur. Mais quelle est la valeur ajoutée de la mise en capture de Lambda dans le foncteur dérivé intérieur ( STR STRUTER code>), au lieu de mettre l'instance et les pointeurs de méthode. Il ajoute une autre couche d'indirection. La 4ème idée semble également bonne pour un microcontrôleur.
@Gyorgyszekely, ce n'est pas vraiment plus indirect. Cela prend également en charge tout foncteur capturé (foncteur, non lambda), au lieu d'appeler simplement des fonctions membres sur un objet.
Un solide, efficace, Comme nous sommes intégrés, nous voulons éviter l'allocation de mémoire . J'écrirais donc un Il stocke également un déménageur, un destructeur et un Pointeur de fonction Invoker. Ces pointeurs peuvent être localement dans le exemple en direct . P> Une autre chose manquante est une qualité de haute qualité la tâche ci-dessus Prend en charge le déplacement, mais pas copier. Ajout de copie signifie que tout stocké doit être copié et nécessite une autre fonction dans la machine à livrer (avec une implémentation similaire à une petite quantité de C ++ 14 a été utilisé, à savoir le Une autre amélioration serait d'apprendre à traiter comment traiter Conversion des fonctions de l'élément à la fonction Les pointeurs sont non seulement un comportement non défini, souvent la convention appelante de Une fonction est différente d'une fonction membre. En particulier, de telles différences peuvent être subtiles et peuvent atteindre lorsque vous changez de code non liée ou que la version du compilateur change , ou quoi que ce soit d'autre. J'éviterais donc que si vous avez peu d'autre choix. P> Comme indiqué, la plate-forme manque de bibliothèques. Chaque utilisation de exemple en direct , à propos d'une douzaine de lignes par Je mettrais cette "réimplémentation de la bibliothèque STD" dans Si vous le pouvez, utilisez un lien qui plie des fonctions identiques ensemble, comme la lieur d'or. Le métaprogramming de modèle peut provoquer un gonflement binaire sans une liaison solide pour la bande. P> P> std :: fonction
small_task
sz code> et alignement
algn code> dans lequel il stocke ses objets effacés. P>
small_task code> (localité maximale) ou dans un manuel
structure {/*...*/} const * Table Code>. P >
Void (args ...) code> qui ne se soucie pas si le passage apportable a une valeur de retour. P>
Move code>, sauf
src code> est
const code> et non
std :: déplacer code>). p>
activer_if_t code> et
décrypy_t code> alias et similaire. Ils peuvent être facilement écrits en C ++ 11 ou remplacés par
typename std :: activation_if > :: Type code>. P>
Bind code> est meilleur remplacé par Lambdas, honnêtement. Je ne l'utilise pas même sur des systèmes non intégrés. P>
small_task code> s plus petit / moins aligné en stockant leur < Code> VTable CODE> POINTER plutôt que de la copier dans la mémoire tampon code> DATA CODE> dans un autre
Tablevisible code>. Cela encouragerait à utiliser
small_tasks code> suffisamment grand pour votre problème de problème. P>
ceci code> est transmis dans un registre particulier sous certaines conventions d'appel. P>
std code> ci-dessus est minuscule, donc je vais simplement les écrire: p>
déplacer h1>
Transférer h1>
décroissance h1>
is_convertible h1>
résultat_of h1>
aligné_storage h1>
is_same h1>
std code> Modèle de bibliothèque dont j'avais besoin. p>
Nomspace NotStd code> pour préciser ce qui est clairement Aller sur. p>
Wow, c'est un peu cohéros C ++, je pense que je dois grandir plus de muscle de modèle pour comprendre toutes les parties de celle-ci. Malheureusement, il repose fortement sur les en-têtes STDC ++ qui ne sont pas disponibles sur la plate-forme cible, je ne peux donc pas l'utiliser directement. +1 pour la 2e partie mentionnant les différences de niveau abi possibles.
@gyor Move, Transférer, Stockage aligné, Decom, IS_Convertable, Activer_if, Résultat_of - Je manque tout? La plupart sont 3-4 lignes chacune et facile à écrire. aligné_storage: Quelles sont les exigences d'alignement de votre plate-forme?
C'est un UC de 8 bits avec 2 kmbytes de RAM et 32kbytes de Flash -> Aucune exigence d'alignement. :)
@Gyorgyszekely ok, fait - pas d'en-têtes utilisés avant mon petit_task code>, tout écrit de Nus C ++ 11. Je pense que tout est compatible C ++ 14 (Sfinae supporté le résultat_of_t, etc.).
@Yakk, j'aimerais utiliser votre code dans un projet. Quelle est la licence pour cela? Quelque chose comme mit, cc-0 ou wtfpl serait parfait :-)
@Yakk, vient de trouver meta.stackexchange.com/questions/271080/... qui dit que le code est autorisé sous la CC-BY-SA, mais cette licence n'est pas vraiment adapté au code et à la problématique dans mon projet actuel. Souhaitez-vous reliciter cela sous la licence MIT, comme les nouvelles contributions de code sur Stackoverflow?
Avant d'essayer d'écrire toutes les choses STL à la main, j'essaie d'utiliser la STL que j'ai déjà du compilateur lui-même. Étant donné que la majeure partie du code STL que vous utilisez est l'en-tête seulement, je l'incluais simplement et faites quelques hacks mineurs pour les obtenir compilés. En fait, ID a fait 10 minutes pour le préparer!
J'ai utilisé la version AVR-GCC-5.2.0 sans aucun problème pour la tâche. Je n'ai aucune installation ancienne et je pense qu'il est plus facile d'installer la version actuelle en quelques minutes au lieu de résoudre les problèmes de l'ancien. P>
Après avoir compilé votre code d'exemple pour AVR I GEA IT GOING ERREURS: P > écrivez simplement votre propre pour moi, cela n'a vraiment aucun sens d'écrire un propre Mise en œuvre STL. Ici, j'ai simplement utilisé les en-têtes qui proviennent de l'installation du compilateur (GCC 5.2.0). P> p> __ thort_bad_function_call code> et supprimez-vous du problème de lien " p>
C'est bon à savoir! Les en-têtes STDC ++ semblaient tellement emmêlés, que je pensais qu'ils tirent de nombreuses dépendances d'exécution.
@Gyorgyszekely bien sûr, la mise en œuvre de la STL semble un peu difficile à comprendre, mais il n'ya généralement rien qui nécessite une sorte de code de bibliothèque. Comme déjà dit, la plupart du temps, le code est en tête-tête seulement. Et pour le reste, il est souvent possible de compiler une source unique si la mise en œuvre de la bibliothèque. std :: string et std :: vecteur fonctionne sur AVR comme prévu. Mais oui, il y a un besoin de flash supplémentaire. Mais pas plus de code auto-écrit du tout. Si vous avez besoin de fonctionnalités STL, utilisez STL. Il est testé, intelligent et complet fonctionnel sur AVR. Pas besoin d'écrire propre et peut-être un code sujet d'erreur.
Pour la STD :: String and STD :: Vecteur: Vecteur Avez-vous fourni une implémentation pour de nouvelles et supprimées? Ceux-ci devraient être dans la bibliothèque d'exécution et la FAQ AVR-LIBC (point 6) indique qu'il manque.
@Gyorgyszekely Oui, simplement transmettre à Malloc / Gratuit. Rien de spécial ici!
Stimule une option? Il y a
boost :: fonction code> et
boost :: lid code> dedans.
Honnêtement, je n'ai pas essayé. En regardant Boost :: Fonction et boost :: Les en-tons liés (tonnes d'autres incluses), ce n'est pas clair à quel point ils dépendent des en-têtes STDC ++ et de la bibliothèque C ++ Runtime. Je vais vérifier rapidement si le projet compile du tout avec une en-tête de boost incluse.
Notez qu'un appel de fonction virtuelle n'est pas plus lent qu'un appel via un
STD :: Fonction Code>, si quelque chose, je m'attends à ce qu'elle soit plus rapide.
@Quentin: Vous avez probablement raison. Je me demandais simplement si cela peut être réduit dans un appel direct avec le piratage de style C dans l'option 3, peut-être que quelque chose de similaire est réalisable en C ++. Mais j'ai l'impression qu'au moins 1 indirection est nécessaire pour récupérer les informations de type pour l'appel de la méthode.