티스토리 뷰

반응형

이 글은 C++20 기준으로 작성되었습니다.

 

 

준비

 

Callback 정의 및 Call의 인자 Parameter 지정을 보다 수월히 하기 위해 IDelegate 선언 및 IDelegateArgs 인터페이스를 선언합니다.

 

Delegate.h

class IDelegateArgs
{
};

using IDelegate = void(IDelegateArgs* args);

 

IDelegateArgs 인터페이스 클래스를 상속받아 원하는 형태의 Parameter 클래스를 재선언 합니다.

 

아래는 IDelegateArgs를 상속받아 재선언한 예시 클래스입니다.

 

SessionDelegateArgs.hpp

class CSessionDelegateArgs : public IDelegateArgs
{
public:
	ISession* get() const { return this->_session; }
	void set(ISession* p) { this->_session = p; }
	
public:
	CSessionDelegateArgs(ISession* session) : _session(session) {}
    
private:
	ISession* _session;
};

 

Callback을 담을 CEventDelegate클래스를 선언 및 정의합니다.

 

EventDelegate.hpp

class CEventDelegate
{
public:
	void operator = (const std::function<IDelegate>& f)
	{
		this->_f = f;
	}

	bool operator == (const CEventDelegate& d)
	{
		return this->_id == d._id;
	}

	bool operator != (std::nullptr_t)
	{
		return _f != nullptr;
	}

public:
	void operator () (IDelegateArgs* args) { this->_f(args); }
	unsigned int id() { return this->_id; }
	void id(unsigned int i) { this->_id = i; }

public:
	CEventDelegate(const std::function<IDelegate>& f) : _id(0), _f(nullptr) { this->_f = f; }
	virtual ~CEventDelegate() {}

private:
	unsigned int _id;
	std::function<IDelegate> _f;
};

 

CEventDelegate를 저장하고 실행해 줄 CEventDelegateHandler를 선언 및 정의해줍니다.

 

EventDelegateHandler.hpp

class CEventDelegateHandler
{
public:
	void operator () (IDelegateArgs* args)
	{
		for (auto const& it : this->_events) {
			(*it)(args);
		}
	}

	void operator += (CEventDelegate* d)
	{
		assert(d != nullptr);

		for (auto const& it : this->_events) {
			if (it == d) {
				return;
			}
		}
		d->id(this->_event_id++);
		this->_events.push_back(d);
	}

	void operator -= (CEventDelegate* d)
	{
		assert(d != nullptr);

		for (auto it = this->_events.begin(); it != this->_events.end(); it++) {
			if ((*it) == d) {
				delete (*it);
				this->_events.erase(it);
				return;
			}
		}
	}

public:
	CEventDelegateHandler() : _event_id(0) {}
	virtual ~CEventDelegateHandler()
	{
		for (auto const& it : this->_events) {
			delete it;
		}
	}

private:
	unsigned int _event_id;
	std::vector<CEventDelegate*> _events;
};

 

 

사용 예시

 

아래는 Callback 함수 선언 예시입니다.

void onConnected(IDelegateArgs* args);
void onDisconnected(IDelegateArgs* args);

 

CEventDelegate 및 CEventDelegateHandler 사용 예시입니다.

CEventDelegateHandler cb_connected;
CEventDelegateHandler cb_disconnected;

// CALLBACK 등록
cb_connected += new CEventDelegate(std::bind(&onConnected, this, std::placeholders::_1));
cb_disconnected += new CEventDelegate(std::bind(&onDisconnected, this, std::placeholders::_1));

 

Parameter 및 Callback call 사용 예시입니다.

CSessionDelegateArgs args(this);
cb_connected(dynamic_cast<Interface::IDelegateArgs*>(&args));
반응형