1

我正在尝试构建一个类来处理关键回调。

为此,我有一个这样定义的地图:

class Keyboard {
public:
   void registerCallback(int key, callback_fn func, bool repeat = false);
   void onKeyEvent(int key, int state);

private:
    typedef std::function<void (int)> callback_fn;

    struct Callback {
        Callback(callback_fn f, bool r)
            : func(f), repeat(r), last_state(-1) {}

        callback_fn func;
        bool repeat;
        int last_state;
    };

    std::unordered_map<int, std::vector<Callback>> callbacks;
};

然后我像这样注册回调:

void Keyboard::registerCallback(int key, callback_fn func, bool repeat) {
    // My understanding is that if there is nothing mapped to the key
    // it will create a new vector. Otherwise it will return the mapped
    // object. I did try checking if anything already exists at the key
    // and if not creating a new vector but it yielded the same results.
    callbacks[key].push_back({ func, repeat });
}

但是,我遇到了一个问题,即映射向量似乎丢失了所有元素。

当我注册回调时,给定键处的向量会增加大小,但是当我尝试用另一种方法迭代向量时,它没有元素。

下面是我对向量进行迭代的方法。

void Keyboard::onKeyEvent(int key, int state) {
    for(auto& callback : callbacks[key]) {
        if(callback.repeat || callback.last_state != state) {
            callback.func(state); 
        }
    }
}

请注意,如果我添加std::cout << callbacks[key].size() << std::endl;到它打印的函数的顶部0

如果这很重要,这是我如何注册回调的示例。

keyboard.registerCallback('w', [](int state) {
    std::cout << "w " << (state == GLFW_PRESS ? "pressed" : "released") << std::endl;
}, true);

我怀疑我的问题源于我更习惯的 Java 映射和 C++ 映射之间的差异

4

2 回答 2

3

让我猜猜:问题是您收到的键码是大写字母('W';字母键码通常是大写的),但为小写字母('w')注册了回调。

于 2013-05-26T20:01:08.607 回答
0

这个问题很可能是区分大小写的问题,因为您的代码没有什么特别之处,并且在调试器中运行 10 秒确认没有发生任何神奇的事情。只要您一直使用相同的“键盘”实例,那么它找不到您正在寻找的“键”的唯一原因是因为它与您注册的键不同。

您是否在调试器中单步执行并确定要搜索的密钥?你试过输出吗?

如果您必须处理可变大小写,那么您始终可以重载“unordered_map”以使用自定义散列函数,它可以为您进行无大小写比较。

于 2013-05-26T20:42:37.060 回答