-2

Getting below error for the code given below. Trying to have 3 std::function inside an template class and then initialize them with different functions from different classes.

Why is this error happening? What's wrong with below code?

enter image description here

template <typename T>
class CFuntion {
public:
    std::function<void()> callback_1;
    std::function<void()> callback_2;
    std::function<void()> callback_3;

    template <typename A, typename B, typename C>
    CFuntion(A cb1, B cb2, C cb3)
        : callback_1(cb1), callback_2(cb2), callback_3(cb3)
    { }
};

class Impl1 {
public:
    void do_something1() {
        cout << "Inside Impl1 do_something1" << endl;
    }

    void do_something2() {
        cout << "Inside Impl1 do_something2" << endl;
    }
};

class Impl2 {
public:
    void do_something1() {
        cout << "Inside Impl2 do_something1" << endl;
    }

    void do_something2() {
        cout << "Inside Impl2 do_something2" << endl;
    }
};

class Impl3 {
public:
    void do_something1() {
        cout << "Inside Impl3 do_something1" << endl;
    }

    void do_something2() {
        cout << "Inside Impl3 do_something2" << endl;
    }
};

int main()
{
    unique_ptr<CFuntion<void>> ptr1 = make_unique<CFuntion<void>>(std::bind(&Impl1::do_something1, &Impl2::do_something1, 
                                        &Impl3::do_something2));
    ptr1->callback_1();
    ptr1->callback_2();
    ptr1->callback_3();

    system("pause");
    return 0;
}
east1000
  • 1,240
  • 1
  • 10
  • 30
D K
  • 71
  • 6
  • `CFunction` has two constructors - a constructor you provided that takes three arguments, and a copy constructor that takes `const CFunction&`. You are trying to pass a single argument that's a bind expression, `std::bind(x, y, z)`. None of the constructors can take that argument. – Igor Tandetnik Oct 03 '21 at 03:40
  • 2
    In addition, your bind expression doesn't make any sense: you ask it to call `Impl1::do_something1` with two arguments, `&Impl2::do_something1` and `&Impl3::do_something2`. You probably meant three separate `bind` calls. But simple `std::bind(&Impl1::do_something1)` won't work either - `do_something1` is a non-static member function and requires an instance of `Impl1` to be called on. All in all, it's unclear what you are trying to achieve. – Igor Tandetnik Oct 03 '21 at 03:43
  • @IgorTandetnik - i also tried with this code but that too fails, unique_ptr> ptr1 = make_unique>(std::bind(&Impl1::do_something1), std::bind(&Impl2::do_something1), std::bind(&Impl3::do_something2)); – D K Oct 03 '21 at 03:45
  • 1
    My second comment addresses that. – Igor Tandetnik Oct 03 '21 at 03:46

1 Answers1

1

Look at this part:

unique_ptr<CFuntion<void>> ptr1 = make_unique<CFuntion<void>(std::bind(&Impl1::do_something1, &Impl2::do_something1, &Impl3::do_something2));
//                                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Here, you pass only one object to your CFunction<void>'s constructor. What you needed might be this:

// You need to pass temporary objects to 'std::bind()' to bind non-static member functions
Impl1 obj1;
Impl2 obj2;
Impl3 obj3;
std::unique_ptr<CFuntion<void>> ptr1 = std::make_unique<CFuntion<void>>(std::bind(&Impl1::do_something1, obj1), std::bind(&Impl2::do_something1, obj2), std::bind(&Impl3::do_something2, obj3));

Or, by looking at your Impl1, Impl2 and Impl3 classes it seems you could just make their member methods static (As none of those three classes seem to need any sort of distinction between their objects or have any instance variables to access/modify.):

class Impl1 {
public:
    static void do_something1() {
        cout << "Inside Impl1 do_something1" << endl;
    }

    static void do_something2() {
        cout << "Inside Impl1 do_something2" << endl;
    }
};

class Impl2 {
public:
    static void do_something1() {
        cout << "Inside Impl2 do_something1" << endl;
    }

    static void do_something2() {
        cout << "Inside Impl2 do_something2" << endl;
    }
};

class Impl3 {
public:
    static void do_something1() {
        cout << "Inside Impl3 do_something1" << endl;
    }

    static void do_something2() {
        cout << "Inside Impl3 do_something2" << endl;
    }
};

That way, you just need to do this, which appears to be what you want to do:

std::unique_ptr<CFuntion<void>> ptr1 = std::make_unique<CFuntion<void>>(std::bind(&Impl1::do_something1), std::bind(&Impl2::do_something1), std::bind(&Impl3::do_something2));
Ruks
  • 3,886
  • 1
  • 10
  • 22
  • Thanks for the answer. One question though, if i need to pass arguments to do_something functions, how can that be done? – D K Oct 03 '21 at 03:52
  • 2
    You can put the argument values in `std::bind`, `std::bind(&Impl1::do_something1, 12, "abc", 'a')`, etc. Also, the [cppreference page of `std::bind()` might be useful for you](https://en.cppreference.com/w/cpp/utility/functional/bind). – Ruks Oct 03 '21 at 03:54