Domanda

Sto cercando di memorizzare i puntatori a funzione membro da modelli di questo tipo: (Questa è una versione semplificata del mio codice reale)

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

Poi voglio fare come quanto segue per ogni metodi di overload in GAPP:

connect(&GApp::foo); 

La chiamata a questo per foo() è ok, ma come posso chiamare questo per foo(double d)? Perchè il seguente non funziona?

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

E mi darà

  

Errore di sintassi: 'doppio' dovrebbe essere preceduto da ')'

Non capisco la sintassi che deve essere utilizzato qui. Questo può essere un qustion stupido, ma uno può aiutare su questo?

È stato utile?

Soluzione

Il tuo codice come scritto non viene compilato. Ho fare alcune "ipotesi" su ciò che si voleva fare, e ho cambiato il codice.

In sintesi, è possibile chiamare la funzione corretta specificando esplicitamente il tipo di parametro di funzione:

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

Se i metodi di connessione sono membri di un modello di classe, allora è necessario solo per specificare il tipo di classe una volta:

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:

In risposta alla nuova esempio di codice, tutte le informazioni viene passato. Il caso "raro" è il caso 'signal_void' come questo è dove il segnale ha un argomento di un template, ma la funzione di membro non lo fa. Perciò caso speciale che esempio e poi abbiamo finito. Quanto segue ora 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
}

Altri suggerimenti

Il C ++ Programming Language, 3E, sezione 7.7, P159:

  

Si può prendere l'indirizzo di una funzione sovraccaricata assegnando o inizializzazione di un puntatore a funzione. In tal caso, il tipo del bersaglio viene usato per selezionare dal set di funzioni sovraccaricate. Ad esempio:

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)

Per quanto ne so (non ho controllato), lo stesso vale per le funzioni membro. Quindi la soluzione è probabilmente quella di dividere in due linee:

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

diventa:

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

Non chiamare le variabili tmp; -)

Suppongo che il cast di newacct è sicuro troppo, esattamente per lo stesso motivo. Trasmissione a void (GApp::*)(double) è definito per essere la stessa come l'inizializzazione di una temporanea di tipo void (GApp::*)(double). Dal momento che l'espressione usata per inizializzare è &GApp::foo, mi aspetterei la stessa magia da applicare al cast come si applica a qualsiasi altra inizializzazione di una funzione di sovraccarico. Stroustrup non dice "l'inizializzazione di una variabile puntatore a funzione", dice "l'inizializzazione di un puntatore a funzione". In modo che dovrebbe includere provvisori.

Quindi, se si preferisce una battuta:

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

Comunque, sto supponendo che lo standard ha la stessa idea di coerenza come faccio io, e non ho controllato.

È possibile provare in modo esplicito la fusione il puntatore, per farle sapere quale scegliere, in questo modo:

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

disclaimer: non hanno testato

Questo è il lavoro,

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


  connect(MemberFunctionType);

Perché?

Modifica

hmm .. sì. E 'uguale la soluzione di newacct. Qualcuno può dare una pls soluzione?

Utilizzando libreria di boost :: funzione ...

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

Il mio codice originale è come questo,

connettori ....

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

Segnali ...

signal<double> signal_double;
signal<> signal_void;

Applicazione ...

class GApp
{
public:
    void foo() {}

    void foo(double d) {}
};

Finalmente, il collegamento ...

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

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

C'è modello classs per i segnali (che non sono menzionare qui). Spero che ora è più chiaro della situazione. (O è uguale a previouse?). Che secondo collegamento funziona se non sia foo () (solo foo (doppio)). Questa è la cosa il mio codice mi ha ferito. : (

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top