2010-12-16 7 views
0

Entschuldigung für den Titel, ich weiß nicht, welchen passenden Titel dieses Thema. Ich habe diesen Test-Code http://ideone.com/V8h5K den als Compiler-Fehler, und ich weiß nicht, was mit diesem Code falsch:C++ Syntax err, abstrahiert statische und Member-Funktion in eine Template-Klasse

meine Absicht ist, eine Abstraktion zu schaffen, so dass ich einen Container generischer Funktionszeiger erstellen kann, den don Es ist egal, ob der Funktionszeiger ein Zeiger auf statische Funktion oder eine Elementfunktion ist.

#include <stdio.h> 
#include <vector> 

template<typename R=void, 
typename A=void, 
typename F=R (*)(A)> class Method {  
protected: F method; 
public : Method(F methodPtr):method(methodPtr){ }; 
      virtual R operator()(A argument) { 
       return this->method(argument); 
      }; 
      typedef F FuncType; 
}; 

template<typename A, typename F> class Method<void,A,F> {  
protected: F method; 
public : Method(F methodPtr) :method(methodPtr) { }; 
      virtual void operator()(A argument) { 
       this->method(argument); 
      }; 
      typedef F FuncType; 
}; 

template<typename R, typename F> class Method<R,void,F> {  
protected: F method; 
public : Method(F methodPtr) :method(methodPtr) { }; 
      virtual R operator()() { 
       return this->method(); 
      }; 
      typedef F FuncType; 
}; 

template<typename F> class Method<void,void,F> {   
protected: F method; 
public : Method(F methodPtr) :method(methodPtr) { }; 
      virtual void operator()() { 
       this->method(); 
      }; 
      typedef F FuncType; 
}; 

template<typename C=void, 
typename R=void, 
typename A=void, 
typename F=R (C::*)(A)> 
class ClassMethod : public Method<R,A,F> {  
protected: C& owner; 
public : ClassMethod(C& methodOwner,F methodPtr) 
       :Method<R,A,F>(methodPtr),owner(methodOwner){ }; 
      virtual R operator()(A argument) { 
       return ((this->owner).*(this->method))(argument); 
      }; 
      typedef F FuncType; 
}; 

template<typename C, typename A, typename F> 
class ClassMethod<C,void,A,F>: public Method<void,A,F> { 
protected: C& owner; 
public : ClassMethod(C& methodOwner,F methodPtr) 
       :Method<void,A,F>(methodPtr),owner(methodOwner){ }; 
      virtual void operator()(A argument) { 
       ((this->owner).*(this->method))(argument); 
      }; 
      typedef F FuncType; 
}; 

template<typename C, typename R, typename F> 
class ClassMethod<C,R,void,F>: public Method<R,void,F> { 
protected: C& owner; 
public : ClassMethod(C& methodOwner,F methodPtr) 
       :Method<R,void,F>(methodPtr),owner(methodOwner){ }; 
      virtual R operator()() { 
       return ((this->owner).*(this->method))(); 
      }; 
      typedef F FuncType; 
}; 

template<typename C, typename F> 
class ClassMethod<C,void,void,F>: public Method<void,void,F> { 
protected: C& owner; 
public : ClassMethod(C& methodOwner,F methodPtr) 
       :Method<void,void,F>(methodPtr),owner(methodOwner){ }; 
      virtual void operator()() { 
       ((this->owner).*(this->method))(); 
      }; 
      typedef F FuncType; 
}; 

// ---- implementation ----- 

template<typename A> class MethodList { 
protected: 
    std::vector< Method<void,A> > methods; 
public: 
    void add(typename Method<void,A>::FuncType fp) { 
     this->methods.push_back(Method<void,A>(fp)); 
    } 
    template<class C> void add(typename C& instance, 
    typename ClassMethod<C,void,A>::FuncType fp) { 
     this->methods.push_back(ClassMethod<C,void,A>(instance,fp)); 
    } 
    void invoke(A argument) { 
     typename std::vector< Method<void,A> >::iterator it; 
     for(it=this->methods.begin() ; it!=this->methods.end() ; it++) { 
      (*it)(argument); 
     } 
    } 
}; 


void function1(int arg) { 
    printf("function1(%d)",arg); 
} 

class Class1 { 
public: 
    void function1(int arg) { 
     printf("Class1::function1(%d)",arg); 
    } 
}; 

int main(int argc,char* argv[])       
{  
    Class1 inst; 
    MethodList<int> methodList; 

    methodList.add(function1); 
    methodList.add<Class1>(inst,&Class1::function1); 
    methodList.invoke(123); 

    return 0; 
} 
+0

Es kann hilfreich sein, den Fehlertext anzuzeigen und die Zeilennummer anzugeben. – sje397

+0

@ sj397: Sie können hier sehen: http://ideone.com/V8h5K – uray

Antwort

0

Diese virtuelle wird Memberfunktion instanziiert werden, wenn der umschließenden Klasse auf den meisten Implementierungen instanziiert wird. Sie müssen es nicht auftreten für die Instanziierung verwenden:

virtual R operator()(A argument) { 
    return this->method(argument); 
}; 

jedoch, wenn F ein R(C::*)(Args) ist, wird die Verwendung von this->method sein schlecht ausgebildet. Also diese Ableitung ist falsch:

// will instantiate Method<R, A, F> 
class ClassMethod : public Method<R,A,F> 

FWIW Sie brauchen nicht zu spezialisieren für Rvoid zu sein. Sie können eine return-Anweisung in einer void-Funktion mit einem Ausdruck haben, der den Typ void hat.

// works fine with R being void 
virtual R operator()(A argument) { 
    return static_cast<R>(this->method(argument)); 
}; 

WOW, jetzt sehe ich Sie auch Objekte in Ihrer MethodList Klassenvorlage schneiden. Wenn Sie nicht wissen, worum es bei "Slicing" geht, empfehle ich Ihnen, zuerst grundlegende C++ - Themen zu lesen, bevor Sie diese Art von Code schreiben.

+0

Ich denke, das sollte instanziiert werden '... zurück ((This -> Besitzer). * (This -> Methode)) (Argument) '... weil ich' this-> methods.push_back (Class (Beispiel fp));; '(Hinweis' Class <> 'statt' Methode <> ') für' add' Funktion der Memberfunktion – uray

+0

@uray wow, jetzt sehe ich, dass du die Objekte sogar * schneidest *. Ich empfehle Ihnen, zuerst ein gutes Buch über grundlegendes C++ zu lesen, bevor Sie versuchen, diese Art von Code zu schreiben. –

+0

kann ich das Slicing-Problem lösen, indem ich einen Zeiger als 'Methode <> *' in 'MethodList' halte, der die Instanz auf dem Heap zugewiesen ist, nur der Zeiger wird geworfen, um auf' vector <> 'geschoben zu werden? – uray