C++ - 함수 핸들러(Funtion Dispatcher) (Code)
온라인 서버 제작자 모임의 핵랑님이 만든 것
비공개 카페라서 링크를 눌러도 멤버가 아니라면 접속할 수 없습니다.
#pragma warning(disable:4819)
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/lambda/lambda.hpp>
#pragma warning(default:4819)
#include <string>
#include <vector>
#include <utility>
#include <iostream>
namespace Dispatcher
{
template<typename IdentifierT, typename FunctorT>
class Mapper
{
private:
typedef std::vector<std::pair<IdentifierT, FunctorT> > FunctorMap;
private:
FunctorMap functorMap_;
public:
bool Add(IdentifierT id, const FunctorT &functor)
{
for (FunctorMap::const_iterator it = functorMap_.begin();
it != functorMap_.end(); ++it)
{
if ((*it).first == id)
{
assert(!"id is already exists.");
return false;
}
}
functorMap_.push_back(std::make_pair(id, functor));
return true;
}
bool Remove(IdentifierT id)
{
bool result = false;
for (FunctorMap::const_iterator it = functorMap_.begin();
it != functorMap_.end(); ++it)
{
if ((*it).first == id)
{
functorMap_.erase(it);
result = true;
break;
}
}
return result;
}
bool DoDispatch(IdentifierT id) const
{
FunctorT functor;
if (Find(id, functor) == true)
{
functor();
return true;
}
return false;
}
template<typename Arg1T>
bool DoDispatch(IdentifierT id, Arg1T arg1) const
{
FunctorT functor;
if (Find(id, functor) == true)
{
functor(arg1);
return true;
}
return false;
}
template<typename Arg1T, typename Arg2T>
bool DoDispatch(IdentifierT id, Arg1T arg1, Arg2T arg2) const
{
FunctorT functor;
if (Find(id, functor) == true)
{
functor(arg1, arg2);
return true;
}
return false;
}
private:
bool Find(IdentifierT id, FunctorT &item) const
{
bool result = false;
for (FunctorMap::const_iterator it = functorMap_.begin();
it != functorMap_.end(); ++it)
{
if ((*it).first == id)
{
item = (*it).second;
result = true;
break;
}
}
return result;
}
};
}
void Func(const std::string &s)
{
std::cout << "Func: " << s << std::endl;
}
void Func(unsigned int n, const std::string &s)
{
std::cout << "Func: " << n << ", " << s << std::endl;
}
struct Test
{
void Func(unsigned int n, const std::string &s, unsigned int x)
{
std::cout << "Test::Func: "
<< n << ", " << s << ", " << x << std::endl;
}
}
using namespace boost;
function<void(const std::string &, const std::string &)> lambda_f = (
std::cout << lambda::constant("lambda expr #1: ")
<< lambda::_1 << lambda::_2 << lambda::constant("\n"));
int main(void)
{
Test test;
// Dispatcher 설정
Dispatcher::Mapper<
unsigned int, function<void(const std::string &)> > mapper;
mapper.Add(0, bind(&Func, _1));
mapper.Add(1, bind(&Func, 10, _1));
mapper.Add(2, bind(&Test::Func, test, 10, _1, 20));
mapper.Add(3, (std::cout << lambda::constant("lambda expr #2: ")
<< lambda::_1 << lambda::constant("\n")));
mapper.Add(4, bind(lambda_f, "Hello, ", _1));
// Dispatcher 테스트
std::string s = "test";
// DoDispatch<std::string>()로 해석. 따라서 std::string 임시 객체 생성됨.
mapper.DoDispatch(0, s);
// 임시 객체 생성을 막기 위해 타입을 명시함
mapper.DoDispatch<const std::string &>(1, s);
mapper.DoDispatch<const std::string &>(2, s);
mapper.DoDispatch<const std::string &>(3, s);
mapper.DoDispatch<const std::string &>(4, "World!");
return 0;
}
이 글은 2019-06-04에 작성되었습니다.