Pergunta

O que há de errado com o seguinte trecho?

#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;
}

Tentando compilar com g ++ - 4.3, parece que cv -qualifier funções sobrecarregadas confundir tanto tr1::mem_fn<> e tr1::bind<> e sai o seguinte erro:

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

Em vez dos seguintes compila trecho, mas parece quebrar o const-correção :

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);

Qualquer pista?

Foi útil?

Solução

A pesquisa é feita no momento em que o constness de this não é conhecido. Você apenas tem que dar-lhe uma dica via vazamento. Tente isto:

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

Você também pode notar aqui que a remoção do const ainda funciona. Isso é porque você deve estar passando x pelo ponteiro (porque o primeiro argumento para um C ++ função membro, o parâmetro implícito this, é sempre um ponteiro). Tente isto em vez disso:

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

Como descoberto durante dentro dos meus comentários abaixo, se você omitir o & como você originalmente fez, você estará passando x por valor , o que geralmente não é o que você quer (embora ele faz pouco prático diferença no seu exemplo particular). Isso realmente parece uma armadilha infeliz para bind.

Outras dicas

Esta questão foi respondida, mas acho que a melhor maneira de especificar uma sobrecarga com bind é especificá-la no modelo:

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

Este método é tão explícita, mas menor do que lançar (com static_cast de qualquer maneira. Mas é mais limpo do que o C-cast, que é o mesmo comprimento.

Como John sugeriu, os problemas surgiram naqueles trechos são os seguintes:

  1. Ao passar um membro-função-ponteiro , é necessário especificar a sua assinatura (em caso de sobrecarga)
  2. bind() são argumentos passados ??por valor.

O primeiro problema é resolvido por vazamento do ponteiro função de membro fornecida ao ligamento:

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

O segundo pode ser resolvido por passando o objeto que pode ser chamado por endereço (como John sugeriu), ou por meio de TR1 reference_wrapper<> - caso contrário, serão passados ??por valor, tornando o quebra const-correção alucinação .

Dado x um objeto que pode ser chamado:

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

bind() encaminhará a ao operator() adequada de acordo com a x constness .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top