Синтаксическая ошибка C ++, абстрагирование статической функции и функции-члена в один шаблонный класс - PullRequest
0 голосов
/ 16 декабря 2010

извините за заголовок, я не знаю, какой подходит заголовок этой темы. У меня есть этот тестовый код http://ideone.com/V8h5K, который как ошибка компиляции, и я не знаю, что не так с этим кодом:

я собираюсь создать абстракцию, чтобы я мог создать контейнер общего указателя функции, который не заботится, является ли указатель функции указателем в статическую функцию или функцию-член.

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

1 Ответ

0 голосов
/ 16 декабря 2010

Эта виртуальная функция-член будет создаваться всякий раз, когда включающий класс создается в большинстве реализаций.Вам не нужно использовать его для этого экземпляра:

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

Однако, когда F является R(C::*)(Args), использование this->method будет неправильно сформировано.Таким образом, этот вывод неверен:

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

FWIW вам не нужно специализироваться на R, являющемся void.Вы можете иметь оператор return в void функции с выражением типа void.

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

ВАУ, теперь я вижу, что вы также нарезаете объекты в шаблоне класса MethodList.Если вы не знаете, что такое «нарезка», я рекомендую вам сначала прочитать основные темы C ++, прежде чем писать такой код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...