c++function-pointersstd-functionstd-invoke

reasons for using std::invoke to invoke std::function object


#include <iostream>
#include <functional>
#include <string>
#include <utility>

class MyClass {
public:
    void printMessage(const std::string &message) const {
        std::cout << "Message: " << message << std::endl;
    }
};

int main() {
    // Create an instance of MyClass
    MyClass myObject;

    // Example using std::function and std::invoke
    std::function<void(const MyClass&, const std::string&)> func =
        &MyClass::printMessage;
    std::invoke(func, myObject, "Hello from std::invoke!");

    // Example using std::function and its operator()
    func(myObject, "Hello from operator() of std::function!");

    // Example without std::function (direct member function pointer)
    void (MyClass::*memberFuncPtr)(const std::string&) const = &MyClass::printMessage;
    (myObject.*memberFuncPtr)("Hello from manual member function pointer!");

    return 0;
}

I understand that std::invokeis a nice wrapper, in particular in the context of member function pointers.

My question is: If I use std::function, is there any reason to use std::invoke (instead of std::function::operator() to invoke the std::function callable? Or does it introduce unnecessary performance overhead?


Solution

  • There is no reasoning of std::invokeing std::function, you already made a manual job for defining std::function template arguments.

    std::invoke is useful when you don't care of how an object is referenced, if it's a reference or a pointer.

      // Create an instance of MyClass
      MyClass myObject;
      MyClass* myObjectPtr = &myObject;
    
      // Example using std::function and std::invoke
      std::function<void(const MyClass&, const std::string&)> func1 =
          &MyClass::printMessage;
      std::function<void(const MyClass*, const std::string&)> func2 =
          &MyClass::printMessage;
    
      func1(myObject, "Hello from operator() of std::function!");
      func2(myObjectPtr, "Hello from operator() of std::function!");
      // Do not compile
      // func1(myObjectPtr, "Hello from operator() of std::function!");
      // func2(myObject, "Hello from operator() of std::function!");
    
      auto func3 = &MyClass::printMessage;  // less typing
      std::invoke(func3, myObject, "Hello from std::invoke!");
      std::invoke(func3, myObjectPtr, "Hello from std::invoke!");