解决循环依赖

时间:2014-09-29 12:42:42

标签: c++ templates circular-dependency

我正在编写自己的小游戏引擎。 为了将选项菜单与主菜单和主游戏等分开,我想到制作一个状态系统,其中上面提到的所有内容都是一个自己的状态。 引擎主循环在当前状态上调用tick()方法。 但是现在引擎对状态之间的交互,何时切换状态等都一无所知。 为了解决这个问题,我实现了以下内容: tick() - 状态方法返回模板类型:commandset。 Engine获取一个Eventhandler来处理tick() - 方法的返回值。 它看起来像这样:

    template<class StateHandler, typename FeedbackType>
    void Engine<StateHandler, FeedbackType>::run()
    {
        run = true;
        clock.restart();

        while (run)
        {
            sf::Time elapsed = clock.restart();
            Win->clear(sf::Color::Black);

            processEvents();

            if (!pause)
            {
                Handler(currentState->tick(elapsed), *this);
                if (overlayState != NULL)
                    Handler(overlayState->tick(elapsed), *this);
            }

            Win->display();
        }

    }

因此,引擎在tick的返回值上调用处理程序,并将自身传递给它。这样Handler就可以与引擎进行交互。 (变量处理程序属于StateHandler类型)

现在,当我想测试所有内容,编写一个Teststate和一个处理程序时,我遇到了麻烦。 对于以后的使用,我打算使用一个类作为处理程序,但为了简单的测试目的,我想使用一个函数。 所以当我想编写函数时,我注意到,我无法定义第二个参数,引擎,因为它的模板参数将是函数的类型(取决于引擎类型,这取决于函数类型...)。

现在我的问题是:如何定义处理程序?或者整个想法是垃圾吗? (这真的很悲惨,因为我有点喜欢)

1 个答案:

答案 0 :(得分:2)

功能是否少得多,值得担心?

struct TestHandler {
    void operator ()(const CommandSet& cs, Engine<TestHandler, TestFeedback>& e) {
    }
};

如果你真的想要一个功能,你必须跳过篮球。对于不正当的快乐,我已经添加了一种方法来完成这项工作:

class any_ref {
public:
  template <typename T>
  any_ref(T& ref)
    : pointer(&ref)
#if !defined(NDEBUG)
    , type(&typeid(T))
#endif
  {}

  template <typename T>
  T& get() const {
    assert(typeid(T) == *type);
    return *static_cast<T*>(pointer);
  }

private:
  void* pointer;
#if !defined(NDEBUG)
  const std::type_info* type;
#endif
};

void TestHandler(const CommandSet& cs, any_ref er) {
  auto& e = er.get<Engine<void (*)(const CommandSet&, any_ref), TestFeedback>>();
}