Sovraccaricato puntatore a funzione membro di template
-
11-09-2019 - |
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?
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. : (