带有观察者模式中的参数的std :: function回调(寄存器主题上的占位符)

时间:2014-12-02 20:55:06

标签: c++ function bind std observer-pattern

我正在使用std :: function和std :: bind基于观察者模式处理输入管理器类。

输入管理器类派生自一个名为“Observable”的类,它包含一个名为“Register(...)”的方法:

  std::map<Event, std::vector<std::function<void()>>> m_observers;

  template <class Observer, class... Args>
  void Register(Event&& event, Observer&& observer, Args&&... args)
  {
      m_observers[std::move(event)].push_back(std::bind(std::forward<Observer>(observer), std::forward<Args>(args)...));
  }

因此,您可以将主题注册到输入管理器。输入管理器将当前输入(从OS给出)调度到其所有侦听器(主体)。为此,将调用主题的注册回调。这个回调应该是任意签名。

在主题类中,我在初始化时调用register,如下所示:

GameApp::InputManager.Register(
    InputType::Keyboard,
    &IntroGameState::OnInput,
    this,
    //sf::Event()
    std::placeholders::_1
  );

发生以下编译器错误:

  

c:\ program files(x86)\ microsoft visual studio   12.0 \ vc \ include \ functional(900):错误C2027:使用未定义类型'std :: tuple_element&lt; 0,_Ftuple&gt;'

如果将有效参数传递给寄存器方法(如args ...),例如“sf :: Event()”,那么一切正常。但是此时我只想注册主题并告诉输入管理器为主题提供一些输入时应该调用哪个回调。我想从输入管理器给出一个参数。而不是副verca。在将主题注册到主题时,我不知道这些论点。应该从经理到主题(通过回调)给出参数。所以我认为寄存器代码中的占位符(在主题方面)会没问题。但是这会导致上面提到的编译器错误。

我有什么想法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

您正在尝试填写表单

的插槽
std::function<void()>

调用带std::bind的{​​{1}}作为参数之一的结果。绑定器提供std::placeholders::_1,它接受​​一个参数,operator()期望能够使用none调用它。这就是为什么这不能编译。

如果我了解您正确尝试的内容,则地图应为

类型
std::function

其中 // v---- here ----v std::map<Event, std::vector<std::function<void(SomeClass const &)>>> m_observers; 封装了您需要传回回调数据的数据。