Je voudrais réduire la quantité de syntaxe requise pour faire référence à une fonction et je me demandais s'il y avait un moyen de faire quelque chose comme:
(NON COMPILABLE)
#define pushToLastUsed mSomeLongStackFIFOObject.push_back // some code using it here #undef pushToLastUsed
alors je pourrais faire quelque chose comme:
mSomeLongStackFIFOObject.push_back(10);
au lieu de:
pushToLastUsed(10);
Bien sûr, je pourrais faire une macro comme:
using pushToLastUsed = mSomeLongStackFIFOObject.push_back; // or auto pushToLastUsed = mSomeLongStackFIFOObject.push_back;
mais je préfère ne pas utiliser de macros.
4 Réponses :
Une solution pourrait être d'utiliser une expression lambda pour capturer l'appel de fonction dans un objet appelable:
#include <vector>
void foo(std::vector<int> & bar)
{
auto pushToLastUsed = [&bar](int index) {
bar.push_back(index);
};
pushToLastUsed(10);
}
Bien qu'à mon avis, il y ait très peu à gagner à faire cela, même si vous remplacez bar par un identifiant très long.
Ma première idée allait dans le sens de l'autre réponse. Sur une deuxième lecture de votre question, je comprends que c'est principalement le nom long de l'objet que vous voulez éviter de répéter. Le masquage d'un appel à une fonction standard doit être fait avec précaution car son principal effet est de masquer votre code. Tout le monde sait ce que fait push_back , mais même vous oublierez probablement ce que fait exactement pushToLastUse . Une autre option consiste à alias uniquement le mSomeLongStackFIFOObject avec un nom plus court comme dans
auto& short_name = mSomeLongStackFIFIObject; short_name.push_back(10);
Lorsque vous écrivez mSomeLongStackFIFOObject.push_back (10); vous appelez en fait SomeLongStackFIFOClass :: push_back (& mSomeLongStackFIFOObject, 10);
Une option est à faire:
static inline void pushBack(int n) { mSomeLongStackFIFOObject.push_back(n); }
Et puis:
m.push_back(10);
Cela le raccourcira et vous permettra toujours d'utiliser n'importe quelle variable que vous aimez.
Si la variable est globale, vous pouvez toujours faire:
auto& m= mSomeLongStackFIFOObject;
Si vous essayez de raccourcir l'accès, je suppose que vous êtes utiliser la variable plus d'une fois; alors il pourrait avoir un sens d'essayer de mettre tous les accès dans une fonction qui appartient à la classe.
Je suppose que lorsque vous faites auto & m, la référence est comme un appel direct, n'est-ce pas? Donc m.push_back devrait littéralement compiler avec le même code que mSomeLongStackFIFOObject.push_back iirc?
auto & m = mSomeLongStackFIFOObject puis m.push_back est du point de vue du langage équivalent à auto mp = & mSomeLongStackFIFOObject puis mp-> push_back . Mais je pense que tout compilateur moderne optimiserait cela.
En fait, je ne vois pas comment cela répond à la question. Il offre une alternative qui pourrait avoir une pertinence pratique. Mais du point de vue linguistique, cela ne résout pas le problème décrit dans la question.
Vous pouvez obtenir le comportement souhaité en liant l'objet mSomeLongStackFIFOObject à la fonction membre push_back et en utilisant un espace réservé pour son argument. Cela nécessite au moins un compilateur C ++ 11.
Prenons l'exemple suivant:
#include <functional>
#include <iostream>
struct A {
void push_back(const int& n) { std::cout << "push_back(" << n << ")\n"; }
};
int main() {
A mSomeLongStackFIFOObject;
std::function<void(const int&)> pushToLastUsed = std::bind(
&A::push_back,
&mSomeLongStackFIFOObject,
std::placeholders::_1
);
pushToLastUsed(10); // push_back(10)
}
Quelques remarques à ce sujet:
this comme premier paramètre implicite. La liaison d'une instance de struct A en tant que premier paramètre utilise ce fait. auto fonctionne pour les fonctions membres sans aucun paramètre, mais pas dans le cas ci-dessus. std :: vector :: push_back ), vous devez indiquer explicitement les paramètres du modèle pour le modèle de fonction std :: lier . Voir Utilisation de std :: tr1 :: bind avec std :: vector :: push_back
ou Y a-t-il des problèmes de boost :: bind avec VS2010? pour plus d'informations.
Vous pouvez l'envelopper dans une fonction anonyme. Je ne sais pas si cela poserait des problèmes en C ++, mais je le fais généralement dans Clojure si j'ai besoin localement d'une fonction plusieurs fois; surtout si les arguments restent les mêmes sauf pour un ou deux.
@Carcigenicate Je pense que c'est une bonne idée, mais vous ajoutez un tout petit peu de surcharge que je préférerais éviter, et il ne serait pas disponible avant C ++ 11 (bien que la réponse que je recherche soit post C ++ 11 ).
@MichaelChoi De nombreuses raisons, d'abord vous obscurcissez votre code qui autrement serait propre et explicite, puis vous éloignez le conteneur du lecteur vers lequel vous poussez. Troisièmement, les macros fonctionnelles comme celle-ci ne sont pas recommandées.
Bien sûr, ce n'est que votre exemple, mais en omettant stack, FIFO et object, le nom serait déjà beaucoup plus court. Vous ne devez pas utiliser le nom du type dans le nom de la variable (trop de travail si vous changez le type), et bien sûr c'est un objet.
@Rene Oui, c'est certainement vrai. J'ai intentionnellement ajouté certains attributs comme "objet" et "FIFO" juste pour allonger le nom afin de faciliter la compréhension de la motivation derrière ma question.
@plasmacel je vois. J'éviterais certainement les macros fonctionnelles en premier lieu, mais je peux voir à quel point cacher le conteneur au lecteur pourrait être un gros problème.
@MichaelChoi Ne vous inquiétez pas des frais généraux liés à l'utilisation de fonctions anonymes. Tous les principaux compilateurs sont exceptionnellement bons pour insérer des lambdas.