我正在构建一个复杂的可扩展系统。细节并不重要,但是除了这一期,我真的很喜欢设计。
我有一个类型T的接口WithState<T> : Subject
。>>
有问题的类以template <typename... StateTypes>
为模板。
它具有std::tuple<std::shared_ptr<WithState<StateTypes>>...>>
。
我有一个函数std::any getStateFor(std::shared_ptr<Subject>)
(其中WithState<T> : Subject
)。
我也有一个函数void handleStates(StateTypes... states)
(在这一点上,也可以取一个元组,更容易些)]
现在我需要将所有这些部分插入在一起:我需要将元组中的元素上移到shared_ptr<Subject>
,然后依次将getStateFor
应用于这些元素中的每一个,并将std::any_cast
的结果按StateTypes...
的顺序进行应用,然后将所有这些作为参数包一次转发到handleStates
。
((在此之前被标记为XY问题:较高级别的抽象不关心具体的状态类型,而我想以尽可能多的类型安全性来实现较低部分。到目前为止,这种方法对我来说看起来不错需要)
我可能可以通过将元组转换为向量,对每个元组应用getStateFor
,然后编写适用于适当的any_cast
的递归函数来实现,但是我仍然不知道如何将结果收集到具有不同类型的元组。我想知道这是否适用于智能折叠表达式...
这里是现有代码的骨架:
#include <memory>
#include <tuple>
#include <any>
#include <iostream>
#include <cassert>
#include <functional>
// ignoring references and const for brevity
class Subject {
public:
/* deleted copy assignment and constructor */
// this is here so that the example works
virtual std::any getState() = 0;
};
template <typename T> class WithState : public Subject { };
template <typename... StateTypes>
class StateHandler {
public:
std::tuple<std::shared_ptr<WithState<StateTypes>>...> subjects;
// this one is actually in another class, but it doesn't matter
void handleStates(StateTypes... states);
void handleStatesForSubjects(std::function<std::any (std::shared_ptr<Subject>)> getStateFor) {
// how do I implement this?
}
};
int main() {
struct foo { int a; int b; };
struct WithInt : public WithState<int> {
std::any getState() override { return 17; }
};
struct WithFoo : public WithState<foo> {
std::any getState() override { return foo { 1, 2 }; }
};
StateHandler<int, foo> handler;
handler.subjects = {
std::make_shared<WithInt>(), std::make_shared<WithFoo>() };
handler.handleStatesForSubjects([](auto subj) { return subj->getState(); });
}
但是,这仍然缺少具体类型的std::any_cast
。
有什么想法吗?
我正在构建一个复杂的可扩展系统。细节并不重要,但是除了这一期,我真的很喜欢设计。我有一个接口WithState
主要问题是您的元组包含std::shared_ptr<WithState<StateTypes>>...
,因此apply
会尝试使用它调用给定的lambda,但是lambda只需要StateTypes&&...
。