C++ 模板类型循环和指向模板实例的非模板指针
C++ template type circularity and non-template pointer to template instance
作为参考,这里是最小的例子:http://coliru.stacked-crooked.com/a/75354688a0a6af64
在这个例子中,我有一个模板类型循环的问题,在我看来,可以通过两种方式解决:
- 使
Controller
成为模板 class 并且 Event
成员指针成为指向模板 class 实例的非模板指针(但是如何?)
- 使用
std::any
或类似的东西来保持 Controller
class 非模板(如示例中所示,但不编译)
使这项工作干净利落的最佳方法是什么?
编辑:link 已更新
问题好像不是你想的那样
std::vector<std::any> modules;
//...
for(auto mod : modules) { mod.dispatch(Event{event, this}); } // should probably use an algorithm here
首先,您不能像那样迭代 tuple
。其次any
没有调度方法。
您不能完全键入接受模板参数的擦除仿函数。
但是如果您知道要处理的模板参数的子集,std::any
/std::variant
可能会有所帮助:
在您的情况下,不受支持的事件不执行任何操作,因此“您的”控制器:
template <typename ... Modules>
class Controller {
public:
std::tuple<Modules...> modules;
template<typename evt_t>
void emit(evt_t event) {
std::apply([this](auto&&... args) {((args.dispatch(Event<evt_t>{event, this})), ...);}, modules);
}
Controller(std::tuple<Modules...> _modules) : modules{_modules}{}
};
变成
class Controller {
std::function<void(std::any)> func;
public:
template<typename evt_t>
void emit(evt_t event) {
func(event);
}
template <typename ... Modules, typename EventTags>
Controller(std::tuple<Modules...> tmodules, EventTags event_tags)
{
func = [=, this](std::any any_ev){
auto f = [&, this](auto tag){
using EventType = typename decltype(tag)::type;
if (auto* ev = std::any_cast<EventType>(&any_ev)) {
std::apply([=, this](auto&&... modules) {((modules.dispatch(Event<EventType>{*ev, this})), ...);}, tmodules);
}
};
std::apply([&f](auto... tags){ (f(tags), ...); }, event_tags);
};
}
};
作为参考,这里是最小的例子:http://coliru.stacked-crooked.com/a/75354688a0a6af64
在这个例子中,我有一个模板类型循环的问题,在我看来,可以通过两种方式解决:
- 使
Controller
成为模板 class 并且Event
成员指针成为指向模板 class 实例的非模板指针(但是如何?) - 使用
std::any
或类似的东西来保持Controller
class 非模板(如示例中所示,但不编译)
使这项工作干净利落的最佳方法是什么?
编辑:link 已更新
问题好像不是你想的那样
std::vector<std::any> modules;
//...
for(auto mod : modules) { mod.dispatch(Event{event, this}); } // should probably use an algorithm here
首先,您不能像那样迭代 tuple
。其次any
没有调度方法。
您不能完全键入接受模板参数的擦除仿函数。
但是如果您知道要处理的模板参数的子集,std::any
/std::variant
可能会有所帮助:
在您的情况下,不受支持的事件不执行任何操作,因此“您的”控制器:
template <typename ... Modules>
class Controller {
public:
std::tuple<Modules...> modules;
template<typename evt_t>
void emit(evt_t event) {
std::apply([this](auto&&... args) {((args.dispatch(Event<evt_t>{event, this})), ...);}, modules);
}
Controller(std::tuple<Modules...> _modules) : modules{_modules}{}
};
变成
class Controller {
std::function<void(std::any)> func;
public:
template<typename evt_t>
void emit(evt_t event) {
func(event);
}
template <typename ... Modules, typename EventTags>
Controller(std::tuple<Modules...> tmodules, EventTags event_tags)
{
func = [=, this](std::any any_ev){
auto f = [&, this](auto tag){
using EventType = typename decltype(tag)::type;
if (auto* ev = std::any_cast<EventType>(&any_ev)) {
std::apply([=, this](auto&&... modules) {((modules.dispatch(Event<EventType>{*ev, this})), ...);}, tmodules);
}
};
std::apply([&f](auto... tags){ (f(tags), ...); }, event_tags);
};
}
};