3

I have an input class that has a method that is supposed to take function as an argument.

#include "pixelGameEngine.h"
#include <functional>
class Input
{
public:
    Input() = default;
    Input(const Input&) = delete;
    Input& operator=(const Input&) = delete;

public:
    static void OnDPress(olc::PixelGameEngine* pge, std::function<void()> DoIteration) noexcept
    {
        if (pge->GetKey(olc::D).bPressed)
        {
            DoIteration();
        }
    }
};

And I have a triangle processor class that is supposed to call that function.

#include "pixelGameEngine.h"
#include "input.h"
#include <functional>
class TriangleProcessor
{
    //...
    void DoIteration() noexcept{};
    Input input;
    void Run(olc::PixelGameEngine* pge)
    {
        Input::OnDPress(pge, DoIteration);
    }
}

But I am getting an error "no suitable constructor exists to convert from "void () to "std::function<void ()>"on line Input::OnDPress(pge, DoIteration); with a red squiggly under DoIteration.

Cool_Cornflakes
  • 315
  • 2
  • 13

1 Answers1

7

DoIteration is not a function. It's a method defined on the TriangleProcessor class. The usual std::function constructor you're trying to invoke is for producing std::function instances from callable objects or function pointers. DoIteration has an implied this argument.

Now, you're running this inside of Run, which as it happens has access to that implied this argument. So, in your case, we likely want to pass on the current this value. We can do that

Input::OnDPress(pge, [this]() { this->DoIteration(); });
Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
  • Thanks for the answer. I was wondering why you can't do `Input::OnDPress(pge, this->DoIteration});` – Cool_Cornflakes Jun 26 '21 at 11:38
  • 1
    C++ takes the view that, if you're using an abstraction or technique that has a cost, it should be plainly visible. In a language like Python, you can do exactly that: `Input.OnDPress(pge, self.DoIteration)` works flawlessly. But it implicitly creates a closure. A top-level function `DoIteration` is *just* a pointer; it's super cheap to create and pass around. Whereas `[this]() { this->DoIteration(); })` has to create a special object in memory to store the function pointer, the `this` pointer, and the wrapped behavior of the two together. C++ prefers to make such abstractions explicit. – Silvio Mayolo Jun 26 '21 at 15:01