0

I am trying to pass two functions OnUserCreate and OnUserUpdate as parameters to another function which is then supposed to call them. However, I am getting an error saying

no suitable constructor exists to convert from "int()" to "std::function<int()>"

Here is a reproducible example that vaguely mimics my code.

//ERROR IN LINE win.ProcessMessage(OnUserCreate, OnUserUpdate);
#include <functional>

class Window
{
 public:
    //std::function<int()> creates a function that returns int and takes            
    //no parameter...or so i read not sure if this is right either
    void ProcessMessage(std::function<int()> create, std::function<int()> update)
    {
        create();
        update();
    }
};

class App
{
private:
    Window win;

private:
    int OnUserCreate()
    {
        return 1;
    }

    int OnUserUpdate()
    {
        return 1;
    }

public:
    void Run()
    {
        win.ProcessMessage(OnUserCreate, OnUserUpdate);
    }
};

int main()
{
    App app;
    while (true)
    {
        app.Run();
    }
}
  • 1
    You can only do it this way with global functions. When you're using methods of a class you need to use `std::bind` - see https://stackoverflow.com/questions/7582546/using-generic-stdfunction-objects-with-member-functions-in-one-class – Den-Jason May 28 '21 at 16:47
  • Also see https://en.cppreference.com/w/cpp/utility/functional/function – Den-Jason May 28 '21 at 16:49

1 Answers1

2

You are trying to pass non-static class methods, which require an object instance to call them on. But you are not specifying that object.

Try this instead:

void Run()
{
    win.ProcessMessage(
        std::bind(&App::OnUserCreate, this),
        std::bind(&App::OnUserUpdate, this)
    );
}

Demo

Alternatively:

void Run()
{
    win.ProcessMessage(
        [this](){ return this->OnUserCreate(); },
        [this](){ return this->OnUserUpdate(); }
    );
}

Demo

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thanks for the answer. For the second example, I don't understand why `[this](){ return this->OnUserCreate(); }` and not `[this](){ return this->OnUserCreate; }`. Wouldn't `()` call the function? –  May 28 '21 at 17:26
  • 1
    Yes, it would, which is exactly what you want in that case. You would be assigning the lambda to the `std::function`. So, when `Run()` calls `create()` (or `update()`), it will call the lambda first, which will then call `OnUserCreate()` (or `OnUserUpdate()`). Then the return value of `OnUserCreate()`/`OnUserUpdate()` will be used as the return value of the lambda, which will be used as the return value of `create()`/`update()` (which `Run()` is ignoring). – Remy Lebeau May 28 '21 at 17:39