Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vector of functions with parameters

I have made vectors that contain functions, but they had no argument list. Also, they were not inside of a class. I have a class named Dialog, and I need to store function-pointers with a specific signature. Here is my typedef for these functions:

typedef INT_PTR (*MsgHandler)(WPARAM,LPARAM);

But, since the vector that contains these MsgHandler's will be in my Dialog class, which will be inherited by my CMainWnd class, when I try to push_back the function, the signature of the function is different than that of MsgHandler. Here is my code, the 4 variations of trying to push_back the function in the vector, and the resulting errors for each of them:

typedef INT_PTR (*MsgHandler)(WPARAM,LPARAM);

class Dialog
{
protected:
    Dialog(void); // Must be inherited
    vector<MsgHandler> Handlers;
}

class CMainWnd : public Dialog
{
public:
    INT_PTR MyHandler(WPARAM wp, LPARAM lp) {
        return TRUE;
    }

    CMainWnd(void) {
        // Attempt 1: Handlers.push_back(MyHandler);
        // Attempt 2: Handlers.push_back(&MyHandler);
        // Attempt 3: Handlers.push_back(CMainWnd::MyHandler);
        // Attempt 4: Handlers.push_back(&CMainWnd::MyHandler);
    }
};

Attempt 1 yields the following error:

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

Attempt 2 yields:

error C2276: '&' : illegal operation on bound member function expression

Attempt 3 yields:

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

Attempt 4 yields:

error C2664: 'std::vector<_Ty>::push_back' : cannot convert parameter 1 from 'INT_PTR (__thiscall CMainWnd::* )(WPARAM,LPARAM)' to 'const MsgHandler &'

I think attempt 4 is the closest to being correct, but as stated previously since the function is a member, it alters the signature. How can I store function-pointers in the vector that is defined in the inherited class Dialog that:

  • Have a return type of INT_PTR
  • Have two parameters, the first being a WPARAM, and the second being a LPARAM
  • Are a member of the derived class whose constuctor is the one adding them to the vector

I have heard of using boost::function for doing things like this, but I have looked up documentation for it and I have no idea how to use it, it all seems confusing to me. I would very much like to just add the functions to the vector as if they were variables instead of bogging down my code with bind operations and what not. (May just be because I am ignorant when it comes to boost functions).

What am I doing wrong here, or can I use boost::function to do this? For the boost::function way, I have tried declaring the vector as vector<boost::function<INT_PTR(WPARAM,LPARAM)>> and tried adding MyHandler to it, but that did not work. I would prefer not to use boost if I don't have to, but if someone suggests the boost way of doing this, please clarify how I could do this?

like image 849
Brandon Miller Avatar asked Jan 15 '23 11:01

Brandon Miller


1 Answers

This is where lambdas really shine if you have access to C++11. I'm going to change your code a little bit just because it's slightly easier to get it to work for me, but you should be able to fix it up for your needs quite easily:

#include <vector>
#include <functional>
#include <iostream>

class Dialog
{
protected:
    Dialog() { } // Must be inherited
    std::vector<std::function<bool (int, int)>> Handlers;
};

class CMainWnd : public Dialog
{
public:
    bool MyHandler(int wp, int lp) 
    {
        std::cout << "(" << wp << ", " << lp << ")\n";
        return true;
    }

    CMainWnd() 
    {
       Handlers.push_back([this](int wp, int lp) -> bool { return this->MyHandler(wp, lp); });
       std::cout << Handlers[0](1,1) << "\n";
    }
};

int main()
{
    CMainWnd c;
    return 0;
}

Edit: When using C++03 and boost instead:

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

class Dialog
{
protected:
    Dialog() { } // Must be inherited
    std::vector<boost::function<bool (int, int)> > Handlers;
};

class CMainWnd : public Dialog
{
public:
    bool MyHandler(int wp, int lp) 
    {
        std::cout << "(" << wp << ", " << lp << ")\n";
        return true;
    }

    CMainWnd() 
    {
       Handlers.push_back(boost::bind(&CMainWnd::MyHandler, this, _1, _2));
       std::cout << Handlers[0](1,1) << "\n";
    }
};
like image 109
Yuushi Avatar answered Jan 25 '23 10:01

Yuushi