РЕДАКТИРОВАТЬ, УТОЧНИТЬ:
* Я хочу иметь возможность устанавливать EventHandlers, используя мой собственный класс EventListener, используя перегруженный оператор >>
, и я не могу понять синтаксис для него *
Проблема в том, что перегруженный оператор >>=
не будет соответствовать параметризованному eventHandler, я не знаю, как его правильно объявить !!
OR
Если я сопоставлю его, информация, необходимая для преобразования общего типа T в достойный полезный объект eventHandler, будет исчез !! Мне нужен смешанный синтаксис для определения обобщенного типа T и второго универсального типа в качестве его параметра.
И, используя родителя класса eventHandler, efunctor также бесполезен, так как не параметризован.
Пример:
Ссылка >> new eventHandler (& App :: testFunction, app); /*where app is an istance of App class and testFunction is a method of App. */
У меня есть класс с именем eventHandler
, который идет под этой формой eventHandler<class T>
. Теперь я хочу перегрузить оператор >>
некоторого класса, чтобы позволить мне использовать его следующим образом:
link >> new eventHandler(&App::testFunction, App);
Где App - это другой класс, а testFunction - это, очевидно, метод этого класса. Строка, написанная выше, должна иметь эффект вызова оператора >>=
класса ссылки (обычно называемого Link
).
Я опубликую часть своего кода, чтобы сделать его более понятным:
class Link
{
public:
eventListener* EventListener;
Link()
{
this->EventListener = new eventListener();
}
// PROBLEM
// I am lost here, tried different syntaxes but with no success
//template<template<class G> class T, class F>
template <class T>
Link operator>>=(T& ev)
{
cout << "something";
// Here there is no way to declare the proper eventHandler
eventHandler<?>* event = (eventHandler<?>)ev;
// I need something like T<F>
event->eventName = 'onTest';
this->eventListener->add(event);
return *this;
}
};
template<class T, class F>
T operator>>(T& lhs, F& rhs)
{
return T(lhs)>>=rhs;
}
class App
{
public:
void testFunction(e evt)
{
cout << "it works!" << "\n";
}
};
int main()
{
App* app = new App;
Link* link = new link;
Link link1;
eventHandler<App>* ev = new eventHandler<App>(app, &App::testFunction);
link1 >> ev;
// this line should echo "it works!"
link1.EventListener->triggerEvent("onTest");
// PART 2
// HOW CAN I USE?
// link >> ev;
// when link is a Link*
return 0;
}
Мой вопрос касается того, как объявить метод operator>>=
из Link, чтобы он автоматически включал мне такую функциональность.
Разъяснения:
- Я хочу иметь возможность добавить в класс EventListener новый eventHandler, используя оператор >>
класса Link, имеющий в качестве правого операнда фактический eventHandler;
РЕДАКТИРОВАТЬ 1:
И у меня второй вопрос:
Как объявить перегруженную функцию >>
так, чтобы меня вызывали с указателем на класс Link ... что делать, если я хочу использовать link
с >>
вместо link1
.
Ответ на PART2: Полагаю, мне просто нужно разыменовать указатель, чтобы использовать перегрузку оператора.
ДРУГОЕ РЕДАКТИРОВАНИЕ
Это версия кода, которая может объяснить его немного лучше. Моя проблема заключается в том, что при сбое компилятора при сопоставлении оператора >>=
внутри класса Link оттуда, если это решено правильно, он может работать, проблема в том, что я не могу найти способ сопоставить его и сохранить подпись события.
А теперь лучше пусть код говорит сам за себя:
#include <iostream>
#include <stdio.h>
#include "events/events.h"
using namespace std;
class Link
{
public:
eventListener* EventListener;
public:
Link()
{
this->EventListener = new eventListener();
}
template<class T>
Link operator>>=(const T& ev)
{
ev->eventName = "onReceive";
this->EventListener->add(ev);
return *this;
}
};
template<class T, class F>
T operator>>(T& lhs, const F& rhs)
{
return T(lhs)<<=rhs;
}
class App
{
public:
void testReceive(e evt)
{
cout << "it works" << "\n" << evt.value;
}
};
class demo
{
public:
Link* parent;
void testit(char* msg)
{
parent->EventListener->triggerEvent("onReceive", this, msg);
}
};
int main()
{
App* app = new App;
Link link;
eventHandler<App>* ev = new eventHandler<App>(app, &App::testReceive);
link >> ev;
demo d;
d.parent = &link;
// should output "it works!"
d.testit("here");
return 0;
}
Я также опубликую свои определения событий:
#ifndef EVENTS_H
#define EVENTS_H
#include <stdio.h>
#include <string.h>
#include "clist.h"
#include <string>
enum scope {global = 0, scoped};
struct e
{
void* target;
void* value;
};
class efunctor //abstract
{
public:
std::string eventname;
virtual void operator()(e evt)
{ }
virtual void Call(e evt)
{ }
};
template <class T>
class eventHandler : public efunctor
{
private:
T* scope;
void (T::*eventMethod)(e);
public:
std::string name;
std::string eventname;
eventHandler(std::string eventnam, T* objscope, void(T::*func)(e))
{
this->scope = objscope;
this->eventMethod = func;
this->eventname = eventnam;
}
eventHandler(T* objscope, void(T::*func)(e))
{
this->scope = objscope;
this->eventMethod = func;
}
eventHandler(void(T::*func)(e))
{
this->eventMethod = func;
}
void operator()(e evt)
{
(scope->*eventMethod)(evt);
}
void Call(e evt)
{
(scope->*eventMethod)(evt);
}
};
class eventListener
{
private:
clist< clist<efunctor* > > methods;
public:
template <class T>
void add(T other)
{
other->name = ToString(this->methods[other->eventname].length());
methods[other->eventname][methods[other->eventname].length()] = other;
}
template <class T>
void remove(T other)
{
methods[other->eventname]->remove(other->name);
}
template <class F>
void triggerEvent(std::string name, void* target, F result)
{
e evt;
evt.target = target;
evt.value = (char*)result;
for(methods[name].iterateStart();
!methods[name].eoi();
methods[name].next())
{
(*(methods[name].getCurrentIteration()))(evt);
}
}
};
#endif