Pregunta

Estoy tratando de almacenar punteros de función miembro de plantillas como esta: (Esta es una versión simplificada de mi 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) {}
};

A continuación, quiero hacer como la siguiente para cada métodos sobrecargados en GAPP:

connect(&GApp::foo); 

Al llamar a este para foo() está bien, pero ¿cómo puedo llamar a esto para foo(double d)? ¿Por qué no está funcionando el siguiente?

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

Me dará

  

error de sintaxis: 'doble' debe ser precedido por ')'

No entiendo la sintaxis que debe ser utilizado aquí. Esto puede ser una qustion estúpida, pero cualquiera puede ayudar en esto?

¿Fue útil?

Solución

Su código como está escrito no se compila. Tengo hacer algunos "supuestos" acerca de lo que quería hacer, y he cambiado el código.

Para resumir, se puede llamar a la función correcta al especificar explícitamente el tipo de parámetro de función:

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

Si los métodos de conexión son miembros de una plantilla de clase, entonces sólo es necesario especificar el tipo de clase una 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)
}

ACTUALIZACIÓN:

En respuesta al nuevo código de ejemplo, toda la información se está pasando. El caso "raro" es el caso 'signal_void' ya que es donde la señal tiene un parámetro de plantilla, pero la función miembro no lo hace. Por lo tanto, el caso especial de que el ejemplo y luego hemos terminado. El siguiente ahora 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
}

Otros consejos

El C ++ Programming Language, 3E, Sección 7.7, P159:

  

Puede tomar la dirección de una función sobrecargada mediante la asignación o inicializar un puntero a la función. En ese caso, el tipo del objetivo se utiliza para seleccionar entre el conjunto de funciones sobrecargadas. Por ejemplo:

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)

Por lo que yo sé (no comprobado), lo mismo se aplica a las funciones miembro. Así que la solución es, probablemente, para dividir en dos líneas:

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

se convierte en:

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

Nunca se refiera a las variables tmp; -)

Me imagino que el elenco de newacct es seguro también, por la misma razón. La conversión a void (GApp::*)(double) se define para ser la misma que la inicialización de un temporal de tipo void (GApp::*)(double). Dado que la expresión utilizada para inicializar es &GApp::foo, esperaría que la misma magia que se aplicará al reparto como se aplica a cualquier otra inicialización con una función sobrecargada. BS No dice "inicializar una variable de puntero a la función", dice "inicializar un puntero a la función". Por lo que debe incluir los temporales.

Así que si usted prefiere una sola línea:

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

Sin embargo, estoy suponiendo que la norma tiene la misma idea de la consistencia como yo, y yo no lo he comprobado.

Usted puede tratar de forma explícita el puntero fundición, para hacerle saber cuál elegir, así:

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

renuncia: no han probado

Esto está trabajando,

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


  connect(MemberFunctionType);

¿Por qué?

editar

hmm .. sí. Es igual que la solución de newacct. ¿Puede alguien dar una solución pls?

El uso de la biblioteca impulso :: función ...

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

Mi código original es así,

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

Las señales ...

signal<double> signal_double;
signal<> signal_void;

Aplicación ...

class GApp
{
public:
    void foo() {}

    void foo(double d) {}
};

Finaly, conectando ...

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

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

Hay classs plantilla para señales (que no se menciona aquí). Espero que ahora es más clara la situación. (O es igual a previouse?). Esa segunda conexión funcionará si no hay foo () (sólo foo (doble)). Eso es lo que mi código me hizo daño. : (

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top