C++에서 이벤트 메커니즘 의 간결 한 실현 및 포기 해 야 할 특성
#include <map>
#include <functional>
using namespace std;
template<class Param1, class Param2>
class Event
{
typedef void HandlerT(Param1, Param2);
int m_handlerId;
public:
Event() : m_handlerId(0) {}
template<class FuncT> int addHandler(FuncT func)
{
m_handlers.emplace(m_handlerId, forward<FuncT>(func));
return m_handlerId++;
}
void removeHandler(int handlerId)
{
m_handlers.erase(handlerId);
}
void operator ()(Param1 arg1, Param2 arg2)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2);
}
private:
map<int, function<HandlerT>> m_handlers;
};
addHandler 는 리 턴 함 수 를 std:function 에 완벽 하 게 전달 하여 표준 라 이브 러 리 로 하여 금 각종 리 셋 을 해결 한 다음 에 식별 자 를 되 돌려 바 인 딩 을 취소 하도록 합 니 다.해 보 세 요.잘 작 동 했 습 니 다.
void f1(int, int)
{
puts("f1()");
}
struct F2
{
void f(int, int)
{
puts("f2()");
}
void operator ()(int, int)
{
puts("f3()");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Event<int, int> e;
int id = e.addHandler(f1);
e.removeHandler(id);
using namespace std::placeholders;
F2 f2;
e.addHandler(bind(&F2::f, f2, _1, _2));
e.addHandler(bind(f2, _1, _2));
e.addHandler([](int, int) {
puts("f4()");
});
e(1, 2);
return 0;
}
여기 작은 단점 이 있 지만 모방 함수 에 대해 지침 이나 인용 을 사용 하려 면 직접 연결 할 수 없습니다.이렇게 해 야 합 니 다.
e.addHandler(ref(f2));
e.addHandler(ref(*pf2)); // pf2 f2 ,
문자,하물며 Lambda 표현 식 이 있 는 상황 에서?개선 1.bind 를 좋아 하지 않 는 사람 이 있 습 니 다.사용 하기 귀 찮 습 니 다.addhandler 에 넣 으 십시오.
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2));
return m_handlerId++;
}
2.확장 매개 변수 갯 수 입 니 다.템 플 릿 인자 가 길 어 지지 않 았 습 니 다.변경 하 십시오.
struct NullType {};
template<class P1 = Private::NullType, class P2 = Private::NullType>
class Event
{
public:
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2);
}
};
template<>
class Event<Private::NullType, Private::NullType>
{
public:
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj)));
return m_handlerId++;
}
void operator ()()
{
for ( const auto& i : m_handlers )
i.second();
}
};
template<class P1>
class Event<P1, Private::NullType>
{
public:
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1));
return m_handlerId++;
}
void operator ()(P1 arg1)
{
for ( const auto& i : m_handlers )
i.second(arg1);
}
};
현재 0~2 개의 인 자 를 지원 합 니 다.각 템 플 릿 에 공공 코드 가 있 음 을 알 고 추출 하여 기본 클래스 에 넣 은 다음 에 해 야 할 일 은 텍스트 생 성 기 를 열 어 전체 코드코드 다운로드
View Code
#pragma once
#include <map>
#include <functional>
namespace Utility
{
namespace Private
{
struct NullType {};
template<class HandlerT>
class EventBase
{
public:
EventBase() : m_handlerId(0) {}
template<class FuncT> int addHandler(FuncT func)
{
m_handlers.emplace(m_handlerId, std::forward<FuncT>(func));
return m_handlerId++;
}
void removeHandler(int handlerId)
{
m_handlers.erase(handlerId);
}
protected:
int m_handlerId;
std::map<int, std::function<HandlerT>> m_handlers;
};
}
template<class P1 = Private::NullType, class P2 = Private::NullType, class P3 = Private::NullType, class P4 = Private::NullType, class P5 = Private::NullType, class P6 = Private::NullType, class P7 = Private::NullType, class P8 = Private::NullType, class P9 = Private::NullType, class P10 = Private::NullType>
class Event
: public Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8, _9, _10));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7, P8 arg8, P9 arg9, P10 arg10)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
}
};
template<>
class Event<Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void ()>
{
public:
using Private::EventBase<void ()>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT const obj, FuncT func)
{
m_handlers.emplace(m_handlerId, std::bind(func, obj));
return m_handlerId++;
}
void operator ()()
{
for ( const auto& i : m_handlers )
i.second();
}
};
template<class P1>
class Event<P1, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1)>
{
public:
using Private::EventBase<void (P1)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1));
return m_handlerId++;
}
void operator ()(P1 arg1)
{
for ( const auto& i : m_handlers )
i.second(arg1);
}
};
template<class P1, class P2>
class Event<P1, P2, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2)>
{
public:
using Private::EventBase<void (P1, P2)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2);
}
};
template<class P1, class P2, class P3>
class Event<P1, P2, P3, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3)>
{
public:
using Private::EventBase<void (P1, P2, P3)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3);
}
};
template<class P1, class P2, class P3, class P4>
class Event<P1, P2, P3, P4, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4);
}
};
template<class P1, class P2, class P3, class P4, class P5>
class Event<P1, P2, P3, P4, P5, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4, P5)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5);
}
};
template<class P1, class P2, class P3, class P4, class P5, class P6>
class Event<P1, P2, P3, P4, P5, P6, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4, P5, P6)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5, P6)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5, arg6);
}
};
template<class P1, class P2, class P3, class P4, class P5, class P6, class P7>
class Event<P1, P2, P3, P4, P5, P6, P7, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
};
template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
class Event<P1, P2, P3, P4, P5, P6, P7, P8, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7, P8 arg8)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
}
};
template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>
class Event<P1, P2, P3, P4, P5, P6, P7, P8, P9, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8, P9)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8, P9)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8, _9));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7, P8 arg8, P9 arg9)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
}
};
} // namespace Utility
테스트 코드 의 각종 바 인 딩 방식
View Code
#include "Event.h"
using namespace std;
void f1(int, int)
{
puts("f1()");
}
struct F2
{
F2() { puts("F2 construct"); }
F2(const F2 &) { puts("F2 copy"); }
F2(F2 &&) { puts("F2 move"); }
F2& operator=(const F2 &) { puts("F2 copy assign"); return *this; }
F2& operator=(F2 &&) { puts("F2 move assign"); return *this; }
void f(int, int)
{
puts("f2()");
}
void fc(int, int) const
{
puts("f2c()");
}
};
struct F3
{
F3() { puts("F3 construct"); }
F3(const F3 &) { puts("F3 copy"); }
F3(F3 &&) { puts("F3 move"); }
F3& operator=(const F3 &) { puts("F3 copy assign"); return *this; }
F3& operator=(F3 &&) { puts("F3 move assign"); return *this; }
void operator ()(int, int) const
{
puts("f3()");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Utility::Event<int, int> e;
//
e.addHandler(f1);
int id = e.addHandler(&f1);
e.removeHandler(id); //
//
using namespace std::placeholders;
F2 f2;
const F2 *pf2 = &f2;
e.addHandler(bind(&F2::f, &f2, _1, _2)); // std::bind
e.addHandler(&f2, &F2::f);
e.addHandler(pf2, &F2::fc); //
puts("----addHandler(f2, &F2::f)----");
e.addHandler(f2, &F2::f); //
puts("----addHandler(F2(), &F2::f)----");
e.addHandler(F2(), &F2::f); //
puts("--------");
//
F3 f3;
const F3 *pf3 = &f3;
puts("----addHandler(f3)----");
e.addHandler(f3); //
puts("----addHandler(F3())----");
e.addHandler(F3()); //
puts("--------");
e.addHandler(ref(f3)); //
e.addHandler(ref(*pf3)); //
puts("--------");
// Lambda
e.addHandler([](int, int) {
puts("f4()");
});
//
e(1, 2);
return 0;
}
입 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
React의 특징 2HTML 태그에 이벤트를 할당하려면 이벤트 이름을 camelCase로 명명하고 이벤트 핸들러에 함수를 전달합니다. style을 할당하는 것은 DOM내에 직접 기술하는 방법이나, CSS프로퍼티를 일단 변수에 대입하고 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.