Pergunta

Eu estou tentando ponteiros função de membro de loja por modelos como este: (Esta é uma versão simplificada do meu código real)

template<class Arg1>
void connect(void (T::*f)(Arg1)) 
{
    //Do some stuff
}

template<class Arg1>
void connect(void (T::*f)()) 
{
    //Do some stuff
}

class GApp
{
public:
    void foo() {}

    void foo(double d) {}
};

Então eu quero fazer como o seguinte para cada métodos sobrecarregados em GAPP:

connect(&GApp::foo); 

Chamar esse para foo() é ok, mas como eu posso chamar isso de foo(double d)? Por que o seguinte não está funcionando?

connect((&GApp::foo)(double)); 

Ele vai me dar

erro de sintaxe: 'double' deve ser precedido por ')'

Eu não entendo a sintaxe que deve ser usado aqui. Este pode ser um qustion estúpido, mas qualquer um pode me ajudar nisso?

Foi útil?

Solução

O seu código como escrito não compila. Eu tenho fazer algumas "suposições" sobre o que você queria fazer, e mudaram o código.

Para resumir, você pode chamar a função correta, especificando explicitamente o tipo de parâmetro de função:

connect<double> (&GApp::foo);

Se os métodos de conexão são membros de um modelo de classe, então é necessário especificar o tipo de classe uma vez:

template <typename T> class A
{
public:
  template<class Arg1>
  void connect(void (T::*f)(Arg1)) 
  {
    //Do some stuff
  }

  void connect(void (T::*f)()) 
  {
    //Do some stuff
  }
};

class GApp
{
public:
    void foo() {}
    void foo(double d) {}
};


int main ()
{
  A<GApp> a;
  a.connect (&GApp::foo);            // foo ()
  a.connect<double> (&GApp::foo);    // foo (double)
}

UPDATE:

Em resposta à nova amostra de código, toda a informação está sendo passada. O caso "raro" é o caso 'signal_void' como este é onde o sinal tem um argumento de modelo, mas a função de membro não. Portanto, caso especial que o exemplo e, em seguida, estamos a fazer. A seguir agora compila:

template <class Arg = void>
class signal {};
signal<double> signal_double;
signal<> signal_void;

// Arg1 is deduced from signal<Arg1> and then we use it in the declaration
// of the pointer to member function
template<class T, class Arg1>
void connect ( signal<Arg1>& sig, T& obj, void (T::*f)(Arg1) ) {}

// Add special case for 'void' without any arguments
template<class T>
void connect (signal<> & sig, T& obj, void (T::*f)()) {}


void bar ()
{
  GApp myGApp;

  //Connecting foo()
  connect(signal_void, myGApp, &GApp::foo); // Matches second overload

  //Connecting foo(double)
  connect(signal_double, myGApp, &GApp::foo); // Matches first overload
}

Outras dicas

A C ++ Programming Language, 3E, Seção 7.7, P159:

Você pode obter o endereço de uma função sobrecarregada, atribuindo ou inicializar um ponteiro para a função. Nesse caso, o tipo de alvo é utilizado para seleccionar o conjunto de funções sobrecarregadas. Por exemplo:

void f(int);
int f(char);

void (*pf1)(int) = &f;  // void f(int);
int (*pf2)(char) = &f;  // int f(char);
void (*pf3)(char) = &f; // error: no void f(char)

Tanto quanto eu sei (não marcado), o mesmo se aplica a funções membro. Portanto, a solução é provavelmente a divisão em duas linhas:

connect((&GApp::foo)(double));

torna-se:

void (GApp::*tmp)(double) = &GApp::foo;
connect(tmp);

Nunca variáveis ??chamadas tmp; -)

Eu acho que o elenco de newacct é seguro também, para exatamente a mesma razão. A transmissão para void (GApp::*)(double) é definida para ser a mesma que a inicializar um temporária de tipo void (GApp::*)(double). Desde a expressão usada para inicializar é &GApp::foo, eu esperaria a mesma mágica para aplicar ao elenco como se aplica a qualquer outra inicialização com uma função sobrecarregada. não Stroustrup não dizer "inicializar uma variável de ponteiro-para-função", diz ele "inicializar um ponteiro-para-função". De modo que deve incluir temporários.

Então, se você preferir um one-liner:

connect((void (GApp::*)(double))(&GApp::foo));

No entanto, eu estou supondo que o padrão tem a mesma ideia de consistência como eu, e eu não tenho verificado.

Você pode tentar explicitamente lançando o ponteiro, para deixá-lo saber qual selecionar, como este:

connect((void (GApp::*)(double))&GApp::foo);

IMPORTANTE: não testei-lo

Isso está funcionando,

    typedef void (GApp::*MemberFunctionType)(double); 
    MemberFunctionType pointer = &GApp::foo;


  connect(MemberFunctionType);

Por que isso?

Editar

hmm .. sim. É mesmo como a solução da newacct. Alguém pode dar uma solução pls?

Usando biblioteca boost :: function ...

#include <boost/function.hpp>

template<class Arg1>
void connect(boost::function1<void, Arg1*> fn) 
{
    //Do some stuff
}

template<class Arg1>
void connect(boost::function2<void, Arg1*, double> fn) 
{
    //Do some stuff
}

class GApp
{
public:
    void foo() {}

    void foo(double d) {}
};


int main()
{
    boost::function1<void,GApp*> f1 = (void (GApp::*)(void)) &GApp::foo;
    boost::function2<void,GApp*,double> f2 = (void (GApp::*)(double)) &GApp:foo;
    connect(f1);
    connect(f2);
    return 0;
}

Meu código original é assim,

conectores ....

template<class T, class Arg1>
void connect(signal<Arg1>& sig,T& obj, void (T::*f)()) 
{
//  sig.insert(new GFunction<T, Arg1>(&obj,f));
}

template<class T, class Arg1
void connect(signal<Arg1>& sig,T& obj, void (T::*f)(Arg1)) 
{
//  sig.insert(new GFunction<T, Arg1>(&obj,f));
}

Sinais ...

signal<double> signal_double;
signal<> signal_void;

Aplicação ...

class GApp
{
public:
    void foo() {}

    void foo(double d) {}
};

Finalmente, conectando ...

//Connecting foo()
        connect(signal_void, myGApp, &GApp::foo()); //Ok

//Connecting foo(double)
        connect(signal_double, myGApp, &GApp::foo()); // but ERROR!

Há classs modelo para sinais (que não são mencionar aqui). Espero que agora está mais claro da situação. (Ou é mesmo que previouse?). Essa segunda conexão funcionará se não houver foo () (somente foo (double)). Essa é a coisa que meu código de me machucar. : (

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