1

Right to the point:

I have a class (Button)

I want to make that button execute a non-static member function owned by another class (Game)

public:
template<class Class>
explicit Button(void (Class::*func)(), Class* T) {
//(T->*func)(); // OK

m_PressFunction = [&](){(T->*func)()};
m_PressFunction(); // OK
}
private:
std::function<void()> m_PressFunction{nullptr}; //STAYS NULLPTR?

Problem is: once the scope is left, m_PressFunction becomes nullptr.

How can I store it right?

UPD

Minimal, Complete, and Verifiable example as asked by @aschepler:

#include <functional>
#include <iostream>

class Button {
public:
    explicit Button() {};
    explicit Button(const Button& other) { m_PressFunction = other.m_PressFunction; };
    explicit Button(Button&& other) { m_PressFunction = other.m_PressFunction; };
    Button& Button::operator=(const Button& other) { m_PressFunction = other.m_PressFunction; return *this; };
    Button& operator=(Button&& other) { m_PressFunction = other.m_PressFunction; return *this; };
    ~Button() {};

    template<class Class>
    explicit Button(void (Class::*func)(), Class& T) {
    m_PressFunction = [&]() {(T.*func)(); };
    m_PressFunction(); // OK
    }

    void runPressFunction() { if (m_PressFunction != nullptr) { m_PressFunction(); } else std::cout << "Tried to run nullptr m_PressFunction. IT DOES NOT WORK\n"; };
private:
    std::function<void()> m_PressFunction{ nullptr }; //STAYS NULLPTR?

};

class Game {
public:
    Game::Game() { m_Button = Button(&Game::PressFunction, *this); };

    void runButtonFunction() { m_Button.runPressFunction(); };
private:
    void PressFunction() { std::cout << "Game::PressFunction() called. IT WORKS\n"; };
    Button m_Button;
};

int main() {
    Game game;
    game.runButtonFunction();

    std::cin.get();
}

Well, it's not null anymore (my bad for forgetting to put m_PressFunction into rule of 5), but it's still not working. Any hints?

Jaro
  • 21
  • 4
  • Yep, I need the reference to the function itself. – Jaro May 25 '17 at 18:52
  • `std::function` is probably your best bet, as you can type-erase the class on which the function is called, though you still need to template it on the return and argument types. You'll also need to bind an instance of the class, which you should be able to do using a lambda or `std::bind`. – underscore_d May 25 '17 at 18:52
  • There is no return & no arguments, but still - the biggest struggle is using std::bind with a template (to pass Game::ButtonStart() to Button::std::function) – Jaro May 25 '17 at 18:54
  • `func` and `T` have a lifetime limited to the `Button` constructor, so you should not capture them by reference. – aschepler May 26 '17 at 00:59
  • Can you provide a [mcve] proving that `m_PressFunction` is null afterward? – aschepler May 26 '17 at 00:59
  • Sure. Hm, I see how it's getting the nullptr - I forgot to add m_PressFunction to the rule of 5, but it's still not working.. – Jaro May 26 '17 at 01:47
  • [`0xCCCCCCCC` probably means you've accessed uninitialized memory](https://stackoverflow.com/q/370195/995714) – phuclv May 26 '17 at 02:38

1 Answers1

0

Finally fixed.

template<class Class>
        explicit Button(void (Class::*func)(), Class* const T) {
            m_PressFunction = [T, func]() {(T->*func)(); };
        }
Jaro
  • 21
  • 4