Frage

Ich versuche, Mitglied Funktionszeiger von Vorlagen wie folgt zu speichern: (Dies ist eine vereinfachte Version meines echten Code)

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

Dann möchte ich wie folgt für jede überladene Methoden in GAPP tun:

connect(&GApp::foo); 

Der Aufruf dieser für foo() ok, aber wie kann ich nennen dies für foo(double d)? Warum wird die folgende Arbeit?

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

Es gibt mir

  

Syntaxfehler: 'double' sollte ')

vorangestellt werden

Ich verstehe nicht, die Syntax, die hier verwendet werden müssen. Dies kann eine dumme qustion sein, aber kann jemand mir helfen, auf das?

War es hilfreich?

Lösung

als Ihr Code geschrieben nicht kompilieren. Ich habe einige „Annahmen“ machen, was Sie tun wollten, und haben den Code geändert.

Um es zusammenzufassen, können Sie die korrekte Funktion aufrufen, indem Sie explizit den Funktionsparameter Typ festgelegt wird:

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

Wenn die Verbindungsmethoden Mitglieder einer Klasse-Vorlage sind, dann ist es nur notwendig, den Klassentyp angeben einmal:

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:

Als Reaktion auf das neue Codebeispiel, alle Informationen werden in übergeben. Der „selten“ Fall ist der ‚signal_void‘ Fall wie das ist, wo das Signal ein Template-Argument, aber die Member-Funktion nicht. Deshalb Sonderfall wir das Beispiel und dann sind wir fertig. Im Folgenden nun kompiliert:

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
}

Andere Tipps

Die C ++ Programmiersprache, 3E, Abschnitt 7.7, p159:

  

Sie können nehmen Sie die Adresse einer überladenen Funktion zum Zuordnen oder einen Zeiger zu initialisieren funktionieren. In diesem Fall wird die Art des Ziels wählen aus der Gruppe überladener Funktionen verwendet. Zum Beispiel:

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)

Soweit ich weiß (nicht überprüft), das gleiche gilt für Member-Funktionen. So ist die Lösung ist wahrscheinlich auf zwei Zeilen aufgeteilt:

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

wird:

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

Nie nennen Variablen tmp; -)

Ich würde vermuten, dass newacct des Darsteller zu sicher ist, für genau den gleichen Grund. Gießen void (GApp::*)(double) ist definiert als die gleiche wie eine temporäre vom Typ void (GApp::*)(double) initialisiert. Da der Ausdruck verwendet, um es zu initialisieren &GApp::foo ist, würde ich die gleiche Magie erwartet die Darsteller anzuwenden, wie mit einer überladenen Funktion auf andere Initialisierung gilt. Stroustrup sagt nicht, „einen Zeiger-to-Funktion Variable initialisieren“, sagt er, „ein Zeiger-to-Funktion initialisiert“. So das sollte Provisorien sind.

Wenn Sie also lieber einen Einzeiler:

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

Aber ich gehe davon aus, dass der Standard die gleiche Idee von Konsistenz hat wie ich, und ich habe nicht geprüft.

Sie können versuchen, explizit den Zeiger Gießen, lassen sie wissen, was man zu wählen, wie folgt aus:

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

Disclaimer: habe es nicht getestet

Dies funktioniert,

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


  connect(MemberFunctionType);

Warum?

EDIT

hmm .. ja. Es ist die gleiche wie newacct Lösung. Kann mir jemand eine Lösung geben pls?

Mit boost :: Funktionsbibliothek ...

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

My Original-Code ist wie diese,

Anschlüsse ....

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

Signale ...

signal<double> signal_double;
signal<> signal_void;

Anwendung ...

class GApp
{
public:
    void foo() {}

    void foo(double d) {}
};

Finaly, Verbinden ...

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

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

Es gibt Vorlage classs für Signale (die hier nicht werden erwähnen). Ich hoffe, dass es jetzt mehr klar die Situation ist. (Oder ist es gleich wie previouse?). Diese zweite Verbindung funktioniert, wenn es nicht foo () (nur foo (double)). Das ist das, was mein Code mich verletzt. : (

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top