As an exercise in code architecture, I was writing a C++ wrapper for a window library called GLFW3.
In this library, when a window's X
button is pressed, you can register a callback that reacts to such event. The callback needs to look like this:
void callback_name(GLFWwindow* handle);
That is, it needs to be a pointer to function that returns nothing and takes a pointer to the window handle.
Now, in my wrapper a window is a proper class called Window
. And I would like to transform the GLFW-approach of using callbacks to using an handling function Window::onClose
akin to what Qt does. For example, the default onClose
function would look like this:
class Window {
...
void onClose() {
hide(); // remove the window from view and from taskbar
}
};
The problem
The problem arises when I try to make this work without introducing overhead into the wrapper. The naïve solution is to register the callback in the constructor:
// DOES NOT COMPILE
class Window {
...
Window(...) {
glfwSetWindowCloseCallback(mHandle,
[this](GLFWwindow*) { // When X button is pressed, call this onClose function
onClose();
});
}
This does not compile, because the "callback" needs to capture this
pointer to call a member function, and glfwSetWindowCloseCallback
expects a raw function pointer.
Getting into more complex solutions, one could maintain a map such as std::unordered_map<GLFWwindow*, Window*> handle_to_window
, and do the following:
glfwSetWindowCloseCallback(mHandle,
[](GLFWwindow* handle) {
handle_to_window[handle]->onClose();
});
BUT this would break with inherited classes unless I make the onClose function virtual (which would introduce overhead).
Question
My question is, is there a way to make this work without introducing more overhead? Answers that change the architecture of the wrapper are fair game also.
[this](GLFWwindow*) {
with[&](GLFWwindow*) {
- iirc, i don't know why, but you can't capturethis
explicitly, but you can capturethis
through capturing everything (why? i have no fking idea)Window
contain aGLFWindow*
data-member? Does it contain any other state? (Does it need to contain any other state?) And since I don't know GLF in general, does GLF allow adding arbitrary state to its objects (possibly by inheritance)?