Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Callback implementation question  (Read 3090 times)

0 Members and 1 Guest are viewing this topic.

Erdrick

  • Jr. Member
  • **
  • Posts: 61
    • View Profile
    • Email
Callback implementation question
« on: May 25, 2016, 04:43:54 am »
Hi,

This is not so much a direct technical question (yet) but a call for help to move in the right direction.
I hope this is not too long of a question, but fear it may be.

Problem statement
=================

1.) i have a game class
2.) i have a generic button class
3.) i have a generic menu class
4.) I have button and menu members of game class and they both are drawn on the screen
5.) I want, when the button is pressed, for the menu to open if its currently closed
   
This got me to thinking that my generic button class needs some way of storing a callback function for what to do when the button is pressed.

I started researching callback functions, function pointers, std::function, std::bind, etc and with those were examples that made basic assumptions.

Some of the examples were dealing only with basic functions and not member functions of specific objects.

After looking at a lot of answers and syntax I realized the TOP answer here came closest to describing what I'm trying to do, but still not quite because its hard-coding class type and I haven't really tried using templates at all yet.

http://stackoverflow.com/questions/10537131/how-to-pass-a-method-as-callback-to-another-class

It may be what I'm trying to do is just too far beyond my current C++ skill level?.

On the same question, there was an answer by Ed Heal that looked like an intriguing alternative that may not be as complicated to implement, wondering what people here thought of his answer to use pure virtual functions instead of typedef with std::function to avoid some of the complexity.

Thanks.

Arcade

  • Full Member
  • ***
  • Posts: 230
    • View Profile
Re: Callback implementation question
« Reply #1 on: May 25, 2016, 05:57:54 am »
If I'm understanding you correctly, it sounds like templates may be a good way to go. You may want to spend some time learning about them.

(Disclaimer: I'm just typing this here without testing so my syntax might not be quite right. I also haven't given this much thought, so it's possible there are better solutions)

Your register function in your Button class could look something like this:
template <typename T>
void registerCallback(std::function<void(T *, int)> c)
{
    callback = c;
}
 

Calling the function would then look something like this:
myButton.registerCallback<otherClass>(&otherClass::myCallback);
 

Note that your whole button class will also need to be a template so that its member variable that stores the callback can handle any type. The member variable would be declared as
std::function<void(T *, int)> callback
 
Where T is the generic type.

The code in the stackoverflow answer allows you to register the callback function first and then later decide which object you want to actually "callon". Alternatively, you could pass in the object at the time you do the register. This will allow you to use std::bind such that your button class no longer needs to be generic.

template <typename T>
void registerCallback(T* object, std::function<void(T *, int)> c)
{
    callback = std::bind(c, object, std::placeholders::_1);
}
 

so the callback member variable can simply be
std::function<void(int)> callback
 

and the callon function would likewise be modified such that you no longer pass in the object to call because the button class would already know which one.

Hopefully this gives you some ideas on one way you could proceed.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Callback implementation question
« Reply #2 on: May 25, 2016, 07:52:26 am »
There's no complexity with callbacks. Forget inheritance and virtual functions.

class Button
{
    std::function<void()> callback;
};


class Menu
{
    void open();
};

Button button;
Menu menu;
button.callback = std::bind(&Menu::open, std::ref(menu));
// or...
button.callback = [&]{menu.open();};

PS: remember this is the SFML forum ;)
Laurent Gomila - SFML developer

Erdrick

  • Jr. Member
  • **
  • Posts: 61
    • View Profile
    • Email
Callback implementation question
« Reply #3 on: May 25, 2016, 05:57:49 pm »
Thanks to both of you for your reply, I will review and report back

Recoil

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
Re: Callback implementation question
« Reply #4 on: May 25, 2016, 06:41:12 pm »
Pfft...I had no idea bout "callbacks".  I am still using the events for my render window to check the location of the button, and send the call to the class sub...

Thanks for this post, it gives me something to lookup to fix my pseudo control class ;)

Erdrick

  • Jr. Member
  • **
  • Posts: 61
    • View Profile
    • Email
Re: Callback implementation question
« Reply #5 on: May 26, 2016, 05:37:25 am »
Thank you Arcade and Laurent for your replies, they were both useful and I got a minimal example working while I decide exactly how to implement in my program.  Thank you!

#include <functional>
#include <iostream>

int main()
{
        // There's no complexity with callbacks. Forget inheritance and virtual functions.

        class Button
        {
                public:
                        std::function<void()> callback;
        };

        class Menu
        {
                public:
                        void open() {
                                std::cout << "I was opened" << std::endl;
                        };
        };

        Button button;
        Menu menu;
       
        //button.callback = std::bind(&Menu::open, std::ref(menu));  // Bind implementation
        // or...
        button.callback = [&] {menu.open(); };          // Lamda implementation
        button.callback();                                                      // Returns "I was opened"

        return 0;
}

 

Recoil, I'm glad I could ask a useful question.