user3397145
user3397145

Reputation: 827

What is std::invoke in c++?

I've just been reading about std::thread and std::bind which I've faced with the Callable concept and std::invoke.

I read about std::invoke on cppreference but I didn't understand what it said. Here is my question:
What is std::invoke, std::function, std::bind and the Callable concept? And what is relationship between them?

Upvotes: 58

Views: 42764

Answers (3)

GPrathap
GPrathap

Reputation: 7820

maybe it late, but this is another usage, of std::invoke

    #include <iostream>
    #include <functional>

    class MyClass {
    public:
        void display(int number) {
            std::cout << "Number: " << number << std::endl;
        }
    };


    int main() {
        // Define a typedef for a pointer to a member function
        typedef void (MyClass::*FuncPtr)(int);
        // Use the typedef to declare a pointer to a member function
        FuncPtr fuc = &MyClass::display;
        // // Create an object of MyClass
        MyClass obj;
        // // Call the member function using the object and the pointer
        (obj.*fuc)(42); // samething using std::invoke
        std::invoke(fuc, obj, 67);
        return 0;
    }

Upvotes: 0

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275740

std::invoke takes something callable, and arguments to call it with, and does the call. std::invoke( f, args... ) is a slight generalization of typing f(args...) that also handles a few additional cases.

Something callable includes a function pointer or reference, a member function pointer, an object with an operator(), or a pointer to member data.

In the member cases, the first argument is interpreted as the this. Then remaining arguments are passed to () (except in the pointer-to-member-data-case), with std::reference_wrappers unwrapping.

INVOKE was a concept in the C++ standard; C++17 simply exposed a std::invoke which does it directly. I suspect it was exposed partly because it is useful when doing other metaprogramming, partly because every standard library has an implementation of INVOKE in it already and exposing it was basically free, and partly because it makes talking about INVOKE easier when it is a concrete thing.

Upvotes: 60

edmz
edmz

Reputation: 8494

A Callable object is, apart from C++-specific details, "something that can be called". It need not be a function: C++ has a number of types that can be called, and going through them every time where any could show up (read: generic code) is problematic and too repetitive.

That's what std::invoke is for - it allows a generic object that can be called (which, according to C++17, satisfies the Callable concept) to be invoked effortlessly.

Let's consider a simple example:

void foo() { std::cout << "hello world\n"; };

template <bool b>
struct optionally_callable
{
        std::enable_if_t<b> operator() ()  {   std::cout << "hi again\n";   }
};

int main()
{
    auto c = [] { std::cout << "hi from lambda\n" ;};

    std::invoke(foo);
    std::invoke(c);

    auto o = optionally_callable<true>{};
    //auto o2 = optionally_callable<false>{};

    std::invoke(o);

}

o2 is not callable, that is, std::is_invocable<decltype(o2)>::value is false.

Upvotes: 17

Related Questions