J'ai le code suivant:
template<class T, typename F, typename ... ARGS>
std::function<void()> * invoke(T *t, F const &fn, ARGS... args) {
std::function<void()> *f = new std::function<void()>([=]() { (t->*fn)( args... ); });
return f;
}
4 Réponses :
Votre invoquer la fonction em> est déjà appelé std :: lid code> et si vous voulez vous assurer que les paramètres de FOO ne sont pas copiés, alors combinez lidez em> avec CREF em>:
Tout d'abord, vous devriez vraiment utiliser Deuxièmement, la compilation échoue parce que le type de déduction est conflits entre Vous pouvez également utiliser std :: Transférer code> lors de la gestion des paquets de paramètres. En ce moment, vous prenez tous les paramètres comme des valeurs. Void (T :: * fn) (args ...) code> et args .. . args code>. Le compilateur sera confus sur le point de prendre des types de args code> ou de votre fonction. Par exemple, A :: FOO code> prend un const B & code> mais vous lui donnez un type de valeur B code> également, ce qui conduit à un conflit. Donc, vous avez réellement besoin de deux paquets de paramètres distincts pour éviter cela. P> std :: lid code> qui fait exactement ce que vous êtes Essayer d'accomplir: P> std::function<void()> fn = std::bind(&A::foo, &myA, myB);
Je crée la fonction sur un tas car ce pointeur sera effectivement ajouté à une file d'attente dans Freertos qui copie ses données par valeur à l'aide de MEMCY ().
Dans ce cas, vous pourriez toujours simplement déplacer ce résultat sur le tas comme nouveau STD :: Fonction invoquer code>.
Pour une raison quelconque, si je modifie mon code comme suggéré ([&, T] () {(T -> * fn) (STD :: Transférer
J'ai couru ce code exact et ça n'a pas échoué, alors je ne suis pas sûr de ce qui pourrait en être la cause. Il est difficile de dire juste de votre description. Aucune copie de mon code> doit être faite du tout, car la Lambda stocke une référence au lieu d'une copie.
En fait, je veux une copie (et une seule) des arguments à effectuer avant que la fonction soit ajoutée à la file d'attente, car il n'y a aucune garantie qui et lorsque le thread de réception accédera aux données. Par exemple, si j'invoque une fonction à l'aide d'une variable locale / temporaire (I.E. sur la pile de l'appelant), une copie doit être prise afin que les données soient disponibles pour le fil de réception.
Arguments de Invoke code> et les arguments de votre fonction de membre sont pas em> les mêmes. On obtient une référence de const, l'autre ne le fait pas. Cela doit être reflété dans les types. template<class T,
typename ... ARGS,
typename ... ARGS2> // <---- !!
std::function<void()> * invoke(T *t,
void(T::* fn)(ARGS2...) // <---- !!
ARGS&&... args) { // you do want perfect forwarding
J'ai trouvé une solution qui fonctionne pour moi basée sur les réponses et les commentaires de chacun.
Dans ma demande, je dois m'assurer que l'un, et une seule copie des arguments à la fonction en cours d'invocation est apportée car La fonction sera exécutée dans un fil différent à un moment différent et les données d'origine peuvent ne pas être disponibles (par exemple, une variable temporaire sur la pile). J'avais modifié mon code, comme suggéré, d'utiliser un transfert parfait dans mes fonctions de matrice. Cela a contribué à réduire considérablement des copies inutiles, cependant, j'avais toujours une copie supplémentaire dans la Lambda de ma fonction d'invoque. Il s'avère, j'avais écrit le constructeur de déplacement de mon type de données de manière incorrecte, lorsque la Lambda a créé une copie temporaire des données, il devait être copié deux fois. P>
Voici des extraits de mon code de travail ( avec mon exemple de type de données B): p> J'ai également montré ici une autre fonction, connectez-vous, qui enregistre une lambda à appeler ultérieurement, appelle la fonction d'invocation. p> avec tout cela, seule une seule copie du type de données est faite aussi longtemps que
a) L'argument de la fonction membre (FN) est d'un type de référence
b) le type de données a un constructeur de déplacement de travail p> p>
Pourquoi avez-vous besoin
invoke () code> du tout? Surtout que vous exécutez le risque demyA code> sortir de la portée avantfn code> est utilisé? Pourquoi pas seulement avoir l'appelant créer un Lambda directement, puis le transmettre au besoin?une mya; B myb (5, 6, 7); auto fn = [=] () {mya.foo (myB); }; // utilise fn si nécessaire ... code>