我正在开发一个 C++ 项目,我想将事件分派到不同的模块。我有一个基本事件类和几个派生事件类型(EventA、EventB、EventC)。我的模块继承自模板化模块基类,该基类使用概念和 SFINAE 将事件分派到派生类中的处理程序(如果已定义)。
它可以与模板一起正常工作,但在尝试仅使用 auto 关键字来实现它时则不行。
这是一个具有完整上下文的工作版本:
struct Event {};
struct EventA : Event {};
struct EventB : Event {};
struct EventC : Event {};
class MyModule;
template <typename T>
concept IsEventType = std::is_base_of_v<Event, T>;
template <typename Dispatcher, typename Dispatchable>
concept CanDispatch = requires(Dispatcher* d, const Dispatchable& e)
{
{ d->dispatch(e) };
};
template <typename Derived>
class Module
{
public:
void onEvent(const IsEventType auto& e)
{
dispatchEvent(e, static_cast<Derived*>(this));
}
private:
// This is the problematic function
template<IsEventType Dispatchable, CanDispatch<Dispatchable> Dispatcher>
void dispatchEvent(const Dispatchable& e, Dispatcher* dispatcher)
{
dispatcher->dispatch(e);
}
void dispatchEvent(...) {}
};
class MyModule : public Module<MyModule>
{
public:
void dispatch(const EventA& event) {
std::cout << "Handling EventA in MyModule" << std::endl;
}
void dispatch(const EventB& event) {
std::cout << "Handling EventB in MyModule" << std::endl;
}
};
int main()
{
MyModule m;
m.onEvent(EventA{});
m.onEvent(EventB{});
m.onEvent(EventC{});
}
我尝试编写这个而不是模板版本,但它永远不会被调用
// Also tried CanDispatch<std::remove_cvref_t<decltype(e)>>
void dispatchEvent(const IsEventType auto& e, CanDispatch<decltype(e)> auto* dispatcher)
{
dispatcher->dispatch(e);
}
这似乎是另一个 msvc 错误,在最新的 trunk 版本中已修复。