Function/Method pointers Pushed to a Deque

2019-08-01 17:31发布

问题:

I am making a Queue for running functions. I put the functions that require being called into a std::deque<bool(*)()> Then I later on cycle through the deque calling each function and letting it run, sometimes even doing things based on the return.

The problem I am having is actually with regards to placing these functions inside of the deque.

I have this deque inside a class called A2_Game. I also have a class called Button.

My code resembles the following:

class Button
{
    bool DoInput();
}

class A2_Game
{
    std::deque<bool(*)()> Input_Functions;
    bool EnterName()
}

A2_Game::OtherMethod()
{
    Button* btn1 = new Button();
    Input_Functions.push_back(&A2_Game::EnterName); //The compiler told me to do this and it still won't compile the line..
    Input_Functions.push_back(btn1->DoInput);

    //Loop
}

I cannot determine how to fix my compile errors. I suspect some of you may be able to just tell me outright what needs to be changed/done in order to get this to compile, by looking at what I've shown here. In case that is !true then here are the compile errors.

error C2664: 'std::deque<_Ty>::push_back' : cannot convert parameter 1 from 'bool (__thiscall A2_Game::* )(void)' to 'bool (__cdecl *const &)(void)'

error C3867: 'Button::Doinput': function call missing argument list; use '&Button::Doinput' to create a pointer to member

回答1:

The problem is that the signature of the class methods don't match with the function signature bool (*)(). The signatures of the two methods are bool (Button::*)(); or bool (A2_Game::*)(); respectively. (The actual class to which the method belongs is part of its signature!)

The solution here is to use functors/function objects. Functors are wrapper objects around "callable elements" that are useful if you want to treat functions like objects (in a OOP sense). If you have boost at hand your code could look similar to this (code compiles):

#include <boost/function.hpp>
#include <deque>

class Button
{
public:
    bool DoInput() { return true; }
};

class A2_Game
{
public:
    typedef boost::function<bool()> Functor;
    std::deque<Functor> Input_Functions;
    bool EnterName() { return true; }
    void OtherMethod();
};

void A2_Game::OtherMethod()
{
    Button* btn1 = new Button();
    Input_Functions.push_back(boost::bind(&A2_Game::EnterName, this));
    Input_Functions.push_back(boost::bind(&Button::DoInput, btn1));
}

boost::bind combines a function pointer with the reference to an actual class instance and returns an function object of the same type as A2_Game::Functor.

Note that boost::function has been integrated into the C++11 standard (see here), so if your project supports C++11 simply use #include <functional> and std instead of boost namespaces.



回答2:

if you want to push back functions you can use std::function (or boost if your compiler doesn't support c++11)

std::deque<std::function<bool()> > function_list;
Button* btn1 = new Button();
function_list.push_back([this](){return EnterName();});
function_list.push_back([btn1](){return btn1->DoInput();});

make sure everything in the lambda is still going to be valid when you call it from the function_list.

EDIT: boost equivalent

std::deque<boost::function<bool()> > function_list;
Button* btn1 = new Button();
function_list.push_back(boost::bind(&A2_Game::EnterName,this));
function_list.push_back(boost::bind(&Button::DoInput,btn1));