2012-04-14 6 views
2

Ich habeWie kann ich instanziiert Klasse mit Funktionszeiger als Vorlage arg

template <void (*T)(Entity *), typename Caller> 
class Updater 
{ 
public: 
    Updater(Caller c):m_caller(c){} 
    void process(Entity * e) 
    { 
     (m_caller->*T)(e);    //Is this right? 
    } 
private: 
    Caller m_caller; 
}; 

Ich verstehe ich es wie

Foo f; 
Updater<&Foo::Bar> updater(&f); 

instanziiert kann unter der Annahme, dass Foo hat

void Foo::Bar(Entity *e); 

aber Was ist, wenn es die gewünschte Methode tempiert hat? So,

template <typename T> 
void Bar(T t); 

Wie sollte ich es installieren? So was:?

Foo f; 
Updater<&Foo::Bar<Entity *>> updater(&f); 

Wenn ich das tue in meinem echten Code, ich

bekommen

invalid template argument for ..., expected compile-time constant expression

So 2 Fragen:

1 ist (m_caller->*T)(e); richtig? Wenn nicht, wie rufe ich es an?

2, wie kann ich es instanziieren?

+0

Sind Sie sicher, Sie haben keinen Platz zwischen den> 's in Updater <& Foo :: Bar > Updater (&f);? – Steed

+0

@Steed es heißt "rechtwinklige Klammern" und es ist völlig in Ordnung in C++ 11, siehe http: // www2.research.att.c om/~ bs/C++ 0xFAQ.html # Klammern – relaxxx

+0

Ich glaube nicht, "Updater " ist korrekt, und Foo :: Bar ist ein Zeiger auf Member-Funktion, aber Ihre Vorlage Parameter ist ein Zeiger auf Funktion, sie sind nicht der gleiche Typ. – Cosyn

Antwort

1
template <typename Caller, void (Caller::*Func)(Entity *)> 
class Updater 
{ 
public: 
    Updater(Caller *c):m_caller(c){} 
    void process(Entity * e) 
    { 
     (m_caller->*Func)(e); // use pointer to member operator ->* 
    } 
private: 
    Caller *m_caller; 
}; 

// call like this 
Foo f; 
Updater<Foo, &Foo::Bar> updater(&f); 
+0

danke, ein paar Kommentar obwohl. 1, dies ruft die nicht-templated Version, ich fand, dass für Templated-Version muss ich es wie '& Foo2 :: Template-Leiste ' und 2, 'Template 'funktioniert nicht für mich, ich muss die Argumente wechseln und beide übergeben, welchen Compiler benutzen Sie? – relaxxx

+0

Ich habe den Tippfehler "Celler" -> "Caller" behoben. Ich denke, es sollte jetzt in Ordnung sein ... Ich habe nicht getestet, aber ich habe ähnlichen Code zuvor geschrieben. – user2k5

+0

Kompilieren mit msvc2010 und erhalten 'Fehler C2653: 'Anrufer': ist keine Klasse oder Namespace-Name – relaxxx

0

edit:

user2k5 bearbeitet seine Antwort, so nahm ich es.

meiner früheren msg:

Dank user2k5 ich die richtige Arbeits Code herausgefunden,

Arbeitsprobe folgt: (foo2 kann durch Foo ersetzt werden)

#include <iostream> 

struct Entity { int i; }; 

template < typename Caller, void (Caller::*Func)(Entity *)> 
class Updater 
{ 
public: 
    Updater(Caller *c):m_caller(c){} 
    void process(Entity * e) 
    { 
     (m_caller->*Func)(e); 
    } 
private: 
    Caller *m_caller; 
}; 

struct Foo 
{ 
    void bar(Entity * e) 
    { 
     std::cout << e->i << std::endl; 
    } 
}; 

struct Foo2 
{ 
    template <typename T> 
    void bar(T t) 
    { 
     std::cout << t->i << std::endl; 
    } 
}; 

int main() 
{ 
    Foo2 f; 
    Updater<Foo2, &Foo2::template bar<Entity *>> updater(&f); 
    Entity e; 
    e.i = 5; 
    updater.process(&e); 


    return 0; 
} 
Verwandte Themen