0
#include <iostream>
#include <functional>
class Solver{
public:
    void print(){
        std::cout << "i solved" << std::endl;
    }
};

class ThingHandler{
public:
    void handleThing(Solver& solver){
        std::cout << "i handled something " << std::endl;
        solver.print();
    }
};

class CantHandle{
public:
    void needHelp(std::function<void(Solver&)> handleThing){
        handleThing(); // how do i here pass Solver as a parameter?
    }
};



int main() {
    ThingHandler thingHandler;
    CantHandle cantHandle;
    Solver solver;
    auto fp = std::bind(&ThingHandler::handleThing, thingHandler,solver);
    cantHandle.needHelp(fp);
    return 0;
}

In the class "CantHandle" when i call the helper function it asks for an parameter. This makes sense since the function that's being called is handleThing which takes a ref to a solver as parameter. But i can't seem to figure out the syntax in the class ThingHandler.Should not handleThing already have the parameter bound? I'm getting the following error "no match for call to ‘(std::function) ()"

Full error message:

error: no match for call to ‘(std::function) ()’ 23 |
handleThing(); // how do i here pass Solver as a parameter? note: candidate: ‘_Res std::function<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) const [with _Res = void; _ArgTypes = {Solver&}]’ 685 | function<_Res(_ArgTypes...)>:: |
^~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/include/c++/9/bits/std_function.h:685:5: note: candidate expects 1 argument, 0 provided gmake[3]: * [CMakeFiles/funcObj.dir/build.make:63: CMakeFiles/funcObj.dir/main.cpp.o] Error 1 gmake[2]: [CMakeFiles/Makefile2:73: CMakeFiles/funcObj.dir/all] Error 2 gmake[1]: [CMakeFiles/Makefile2:85: CMakeFiles/funcObj.dir/rule] Error 2 gmake: * [Makefile:118: funcObj] Error 2

Freebi32
  • 23
  • 4
  • please include the full error message – 463035818_is_not_an_ai Dec 14 '19 at 19:00
  • Since you didn't use a placeholder (e.g. `_1`) in the `std::bind` call, it gave a functor with 0 parameters. `needHelp` expects a functor with 1 parameter. – HolyBlackCat Dec 14 '19 at 19:02
  • @HolyBlackCat how do I bind the placeholder? Do you mean something like std::bind(&ThingHandler::handleThing, thingHandler,std::placeholders::_1) But where do I include Solver in this case? – Freebi32 Dec 14 '19 at 19:09
  • 1
    I think your problem is not syntax but semantics. You have a function, `needHelp()`, that accepts a functional that requires a `Solver` parameter, yet `needHelp()` cannot provide that parameter. So why does `needHelp()` expect `std::function`? – JaMiT Dec 14 '19 at 19:10
  • @JaMiT `void(void)` 0_o – bipll Dec 14 '19 at 19:11
  • @JaMiT you might be correct I assumed that needHelp would need to know the parameters that are being used in std::bind. So if I then understand it correctly, the only thing needHelp needs to know is that the its parameter is a function that returns void? It does not need to concern itself with the parameters to that function? – Freebi32 Dec 14 '19 at 19:14
  • @Freebi32 That is largely the point of `std::bind`, yes. – JaMiT Dec 14 '19 at 19:15

2 Answers2

3

The method needHelp expects a function that takes one parameter, but you want to pass a function without parameter. Change this:

void needHelp(std::function<void(Solver&)> handleThing){

to

void needHelp(std::function<void()> handleThing){

Using a lambda rather than bind is usually easier to write and read and often there is no need to use std::function when you can accept any callable:

#include <iostream>

struct Solver{
    void print(){ 
        std::cout << "i solved" << std::endl; 
    }
};

struct ThingHandler{
    void handleThing(Solver& solver){
        std::cout << "i handled something " << std::endl;
        solver.print();
    }
};

struct CantHandle{
    template <typename F>
    void needHelp(F f){
        f();
    }
};   

int main() {
    ThingHandler thingHandler;
    CantHandle cantHandle;
    Solver solver;   
    cantHandle.needHelp(
        [&solver,&thingHandler](){
            thingHandler.handleThing(solver);
        }
    );
    return 0;
}
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
0

Change your method in CantHandle class and add a parameter as Solver type like bellow and pass the data (Solver object) :

class CantHandle{
public:
    void needHelp(std::function<void(Solver&)> handleThing, Solver data){
        handleThing(data); // how do i here pass Solver as a parameter?
    }
};

In the main, also pass solver after fp as the Solver object :

int main() {
    ThingHandler thingHandler;
    CantHandle cantHandle;
    Solver solver;
    auto fp = std::bind(&ThingHandler::handleThing, thingHandler,solver);
    cantHandle.needHelp(fp, solver);
    return 0;
}

The output will be :

i handled something
i solved

According this link and this

  • *"My answer has the output as your. why down voted?"* I didn't downvote, but the code in your answer doesn't compile. You didn't pass a placeholder to `std::bind`, so the resulting functor can only be called with no arguments. – HolyBlackCat Dec 14 '19 at 19:41