62 votes

Utilisation de std::bind avec une fonction membre, utiliser un pointeur d'objet ou non pour cet argument ?

Lorsque vous utilisez std::bind pour lier une fonction membre, le premier argument est les objets this pointeur. Cependant, il fonctionne en passant l'objet à la fois comme un pointeur et non.

Voir par exemple le programme suivant :

#include <iostream>
#include <functional>

struct foo
{
    void bar(int v) { std::cout << "foo::bar - " << v << '\n'; }
};

int main()
{
    foo my_foo;

    auto f1 = std::bind(&foo::bar, my_foo, 1);
    auto f2 = std::bind(&foo::bar, &my_foo, 2);

    f1();
    f2();
}

Clang et GCC compilent tous les deux sans se plaindre, et le résultat fonctionne pour les deux liaisons :

foo::bar - 1
foo::bar - 2

J'ai essayé de comprendre la spécification (section 20.8.9) mais c'est l'un des endroits où elle est loin d'être claire pour moi.

Un seul doit-il être correct, ou les deux le sont-ils ?

49voto

Daniel Frey Points 30752

Les deux sont corrects. 20.8.9.1.2 renvoie à 20.8.2 pour décrire les exigences et l'effet de votre appel aux bind . 20.8.2 est :

20.8.2 Exigences [func.require]

1 Définir INVOQUEZ (f, t1, t2, ..., tN) comme suit :

- (t1.*f)(t2, ..., tN) cuando f est un pointeur vers une fonction membre d'une classe T y t1 est un objet de type T ou une référence à un objet de type T ou une référence à un objet d'un type dérivé de T ;

- ((*t1).*f)(t2, ..., tN) cuando f est un pointeur vers une fonction membre d'une classe T y t1 n'est pas l'un des types décrits au point précédent ;

- t1.*f cuando N == 1 y f est un pointeur vers une donnée membre d'une classe T y t1 est un objet de type T ou une référence à un objet de type T ou une référence à un objet d'un type dérivé de T ;

- (*t1).*f cuando N == 1 y f est un pointeur vers une donnée membre d'une classe T y t1 n'est pas l'un des types décrits au point précédent ;

- f(t1, t2, ..., tN) dans tous les autres cas.

Les deux premières options autorisent à la fois une référence et un pointeur.

La chose importante à noter ici est que la formulation ne no vous limiter aux simples pointeurs. Vous pourriez utiliser un std::shared_ptr ou un autre pointeur intelligent pour garder votre instance en vie pendant qu'elle est liée et cela fonctionnerait toujours avec std::bind comme t1 est déréférencé, peu importe ce qu'il est (à condition, bien sûr, que ce soit possible).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X