Question

Quel est le problème avec l'extrait suivant?

#include <tr1/functional>
#include <functional>
#include <iostream>

using namespace std::tr1::placeholders;

struct abc
{
    typedef void result_type;

    void hello(int)
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    void hello(int) const
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    abc()
    {}
};

int
main(int argc, char *argv[])
{
    const abc x;
    int a = 1;

    std::tr1::bind(&abc::hello, x , _1)(a);
    return 0;
}

En essayant de le compiler avec g ++ - 4.3, il semble que les fonctions surchargées de l’qualificateur cv confondent à la fois tr1::mem_fn<> et tr1::bind<>. L’erreur suivante apparaît:

no matching function for call to ‘bind(<unresolved overloaded function type>,...

Au lieu de cela, l'extrait de code suivant est compilé mais semble rompre la const-correctness :

struct abc
{
    typedef void result_type;

    void operator()(int)
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    void operator()(int) const
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    abc()
    {}
};

...

    const abc x;
    int a = 1;
    std::tr1::bind( x , _1)(a);

Avez-vous un indice?

Était-ce utile?

La solution

La recherche est effectuée à un moment où la constance de this n'est pas connue. Vous devez juste lui donner un indice via le casting. Essayez ceci:

typedef void (abc::*fptr)(int) const; // or remove const
std::tr1::bind((fptr)&abc::hello, x , _1)(a);

Vous remarquerez peut-être également ici que la suppression de const fonctionne toujours. En effet, vous devez passer x par le pointeur (car le premier argument d'une fonction membre C ++, le paramètre implicite &, est toujours un pointeur). Essayez ceci à la place:

typedef void (abc::*fptr)(int) const; // won't compile without const (good!)
std::tr1::bind((fptr)&abc::hello, &x , _1)(a);

Comme cela a été découvert au cours de mes commentaires ci-dessous, si vous omettez le bind comme à l'origine, vous transmettez x par valeur , ce qui n'est généralement pas ce que vous voulez (bien que petite différence pratique dans votre exemple particulier). Cela ressemble en réalité à un piège malheureux pour <=>.

Autres conseils

On a répondu à cette question, mais je trouve que le meilleur moyen de spécifier une surcharge avec bind est de le spécifier sur le modèle:

std::tr1::bind<void(foo::*)(int)>(&foo::bar);

Cette méthode est tout aussi explicite, mais plus courte que le casting (avec static_cast de toute façon. Mais elle est plus propre que le C-cast, qui a la même longueur.

Comme John l'a suggéré, les problèmes soulevés dans ces extraits sont les suivants:

  1. Lorsque vous passez un pointeur de fonction membre , vous devez spécifier sa signature (en cas de surcharge)
  2. bind() sont passés arguments par valeur.

Le premier problème est résolu en projetant le pointeur de fonction membre fourni pour lier:

    std::tr1::bind(static_cast< void(abc::*)(int) const >(&abc::hello), x, _1)(a);

La seconde peut être résolue en passant l'objet appelable par adresse (comme suggéré par John) ou par TR1 reference_wrapper<> - sinon, il sera passé par valeur, ce qui rend la hall-rupture brisant .

Donné x un objet appelable:

std::tr1::bind( std::tr1::ref(x) , _1)(a);

a transmettra operator() au bon <=> conformément à la x constness .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top