我想要#34;还有另一个"回调注册的东西。 扩展公共基本事件类型的不同事件类型将触发相关的回调函数。
这是初稿或想法
#include <functional>
#include <iostream>
#include <unordered_map>
class BaseEvent
{
public:
virtual ~BaseEvent() {}
};
class DerivedEvent_1 : public BaseEvent {};
class DerivedEvent_2 : public BaseEvent {};
// a container holding callback functions
std::unordered_map<size_t/*event*/, std::function<void(BaseEvent)>/*callback*/> _callbacks;
// register callback funtion associated with specific event
template<typename EVT>
void registerCallback(std::function<void(EVT)> cb)
{
std::cout << "store callback associated with event " << typeid(EVT).name() << " [" << typeid(EVT).hash_code() << "]" << std::endl;
//_functions[ typeid(EVT).hash_code() ] = cb; // FIXME
}
// trigger callback function
void triggerCallback(const BaseEvent* e)
{
std::cout << "trigger callback with event " << typeid(*e).name() << " [" << typeid(*e).hash_code() << "]" << std::endl;
//_functions[ typeid(*e).hash_code() ] (*e); // FIXME
}
// callback function for DerivedEvent_1
void callback_1(DerivedEvent_1 event_1)
{
std::cout << "callback_1 called" << std::endl;
}
// callback function for DerivedEvent_2
void callback_2(DerivedEvent_2 event_2)
{
std::cout << "callback_2 called" << std::endl;
}
int main(int argc, char *argv[])
{
registerCallback<DerivedEvent_1>( [](DerivedEvent_1 e) { callback_1(e); } );
registerCallback<DerivedEvent_2>( [](DerivedEvent_2 e) { callback_2(e); } );
DerivedEvent_1 e1;
DerivedEvent_2 e2;
triggerCallback(&e1);
triggerCallback(&e2);
return 1;
}
到目前为止没有真正的实施......
$ g++ -std=c++11 -o testStdFunction testStdFunvtion.cpp
$ ./testStdFunction
store callback associated with event 14DerivedEvent_1 [4527193776]
store callback associated with event 14DerivedEvent_2 [4527193680]
trigger callback with event 14DerivedEvent_1 [4527193776]
trigger callback with event 14DerivedEvent_2 [4527193680]
情况和问题是:
目的是修复registerCallback和triggerCallback中的FIXME代码。所以在运行代码后它们会是这样的
$ g++ -std=c++11 -o testStdFunction testStdFunvtion.cpp
$ ./testStdFunction
store callback associated with event 14DerivedEvent_1 [4527193776]
store callback associated with event 14DerivedEvent_2 [4527193680]
trigger callback with event 14DerivedEvent_1 [4527193776]
callback_1 called
trigger callback with event 14DerivedEvent_2 [4527193680]
callback_2 called
答案 0 :(得分:1)
您可以使用已擦除的包装
以下代码准确打印OP在问题中发布的消息
关键类是BaseWrapper
和模板类Wrapper
此外,我稍微更改了代码周围的功能签名,以使其正常工作。
#include <functional>
#include <iostream>
#include <unordered_map>
#include<memory>
#include<utility>
class BaseEvent
{
public:
virtual ~BaseEvent() {}
};
class DerivedEvent_1 : public BaseEvent {};
class DerivedEvent_2 : public BaseEvent {};
struct BaseWrapper {
virtual void operator()(const BaseEvent *) = 0;
};
template<typename T>
struct Wrapper: BaseWrapper {
std::function<void(T)> fn;
void operator()(const BaseEvent *e) {
fn(*static_cast<const T*>(e));
}
};
// a container holding callback functions
std::unordered_map<size_t/*event*/, std::unique_ptr<BaseWrapper>/*callback*/> _functions;
// register callback funtion associated with specific event
template<typename EVT>
void registerCallback(std::function<void(const EVT &)> cb)
{
std::cout << "store callback associated with event " << typeid(EVT).name() << " [" << typeid(EVT).hash_code() << "]" << std::endl;
auto w = std::make_unique<Wrapper<EVT>>();
w->fn = cb;
_functions[ typeid(EVT).hash_code() ] = std::move(w);
}
// trigger callback function
void triggerCallback(const BaseEvent* e)
{
std::cout << "trigger callback with event " << typeid(*e).name() << " [" << typeid(*e).hash_code() << "]" << std::endl;
(*_functions[ typeid(*e).hash_code() ] )(e);
}
// callback function for DerivedEvent_1
void callback_1(const DerivedEvent_1 &event_1)
{
std::cout << "callback_1 called" << std::endl;
}
// callback function for DerivedEvent_2
void callback_2(const DerivedEvent_2 &event_2)
{
std::cout << "callback_2 called" << std::endl;
}
int main(int argc, char *argv[])
{
registerCallback<DerivedEvent_1>( [](DerivedEvent_1 e) { callback_1(e); } );
registerCallback<DerivedEvent_2>( [](DerivedEvent_2 e) { callback_2(e); } );
DerivedEvent_1 e1;
DerivedEvent_2 e2;
triggerCallback(&e1);
triggerCallback(&e2);
return 1;
}
可以在性能方面改进包装器(例如,使用静态成员方法而不是多态,留给读者作为练习)。
解决方案背后的基本思想是所谓的type-erasure
Google会帮助您查找有关该内容的更多详细信息。