キーのコールバックを処理するクラスを構築しようとしています。
これを行うために、次のように定義されたマップがあります。
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++ のマップの違いに起因すると思われます。