boost function template error

2019-08-12 09:31发布

问题:

I'm developping a class for manage some callbacks such mouse click or display (callback called when window need to be refreshed)

callbacks and handles are saved in maps. I'm trying to create a function that can register a callback in the maps (addCallback).

class CallBackManager {

public:
  enum CallBackType {
    DISPLAY = 1 << 0,
    MOUSE   = 1 << 1
  };

  template<typename T>
  void AddCallback(CallBackType type, int hwnd, T f) {

    if (type & DISPLAY) {
        addDisplayCallback(hwnd, f); // 50 lines of error here
    }

    if (type & MOUSE) {
        addMouseCallback(hwnd, f);   // The same here
    }

  }

private:

  void addDisplayCallback(int hwnd, boost::function<void ()> f) {
    _display_callback[hwnd] = f;
  };

  void addMouseCallback(int hwnd, boost::function<void (int, int)> f) {
    _mouse_callback[hwnd] = f;
  };

  std::map<int, boost::function<void ()>> _display_callback;
  std::map<int, boost::function<void (int, int)>> _mouse_callback;

};

I call those functions like that :

CallBackManager cbm;

cbm.AddCallBack(
  CallBackManager::CallBackType::DISPLAY,
  my_handle,
  boost::bind(&Foo::Display, this)); // boost::function<void ()>

cbm.AddCallback(
  CallBackManager::CallBackType::DISPLAY,
  my_handle,
  boost::bind(&Foo::Mouse, this, _1, _2)): //boost::function<void (int, int)>

And finally the error is :

error C2784: 'T &boost::_bi::list0::operator [](const boost::reference_wrapper<T> &) const' : could not deduce template argument C:\local\boost_1_57_0_b1\boost\bind\bind.hpp   392

I don't understand this error

(here is the code with the compilation error) https://ideone.com/BdW1Ln

回答1:

You're adding the function of T type to both maps, in the same static code path. Of course, you filter it, but that's runtime. This can't work.


Just use separate functions.

It's shorter and more readable.

Live On Coliru

#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <map>

class CallBackManager {

  public:
    enum CallBackType { DISPLAY = 1 << 0, MOUSE = 1 << 1 };
    struct display_callback_t;

    template <typename F>
    void AddDisplayCallback(int hwnd, F f) {
        addDisplayCallback(hwnd, f);
    }

    template <typename F>
    void AddMouseCallback(int hwnd, F f) {
        addMouseCallback(hwnd, f);
    }

    void test() {
        for (auto& f : _display_callback)
            f.second();
        for (auto& f : _mouse_callback)
            f.second(rand(), rand());
    }
  private:
    void addDisplayCallback(int hwnd, boost::function<void()> f) { _display_callback[hwnd] = f; };

    void addMouseCallback(int hwnd, boost::function<void(int, int)> f) { _mouse_callback[hwnd] = f; };

    std::map<int, boost::function<void()>> _display_callback;
    std::map<int, boost::function<void(int, int)>> _mouse_callback;
};

#include <iostream>
struct Foo {

    int my_handle;
    CallBackManager cbm;

    Foo()
    {
        cbm.AddDisplayCallback(my_handle, boost::bind(&Foo::Display, this));
        cbm.AddMouseCallback(my_handle, boost::bind(&Foo::Mouse, this, _1, _2));
    }

    void Mouse(int, int) {
        std::cout << __PRETTY_FUNCTION__ << "\n";
    }
    void Display() {
        std::cout << __PRETTY_FUNCTION__ << "\n";
    }
};

int main() {
    Foo instance;
    instance.cbm.test();
}

Prints

void Foo::Display()
void Foo::Mouse(int, int)