Search code examples
c++c++11c++17stdthreadc++-concepts

What are the usecases and usefulness when passing pointer to data member to std::invoke?


I was reading about std::invoke on cpp reference and was wondering in which situations we would ever need to pass as a first argument a pointer to data member and an object as second argument.

From cpp reference it states this:

Invoke the Callable object f with the parameters args. As by INVOKE(std::forward(f), std::forward(args)...).

where INVOKE(f, t1, t2, ..., tN) is defined as follows:

...

and then the second point is:

Otherwise, if N == 1 and f is a pointer to data member of class

Ok, let's look at this further and suppose I'm using std::thread (which constructor's uses std::invoke):

For example, it is a bit unclear to me when it would be useful (or what can force one) to use a threads this way ?

struct Foo {
    Foo(int num) : num_(num) {}
    void print_add(int i) const { std::cout << num_+i << '\n'; }
    int num_;

    void print_num(int i) const {
        std::cout << i << '\n';
    }
};

int main() {
    const Foo foo(314159);
    std::thread t(&Foo::num_, foo);
    t.join();
    return 0;
}  

And how a pointer to data member can be associated with a callable concept ?


Solution

  • You might think that only pointers to member functions are useful. That is, something like:

    struct Widget {
        bool valid() const;
    };
    
    std::vector<Widget> widgets;
    bool all_valid = std::ranges::all_of(widgets, &Widget::valid);
    

    That would std::invoke the pointer to member function &Widget::valid on each of the Widgets. But you could just as easily have constructed Widget such that valid is just a flag instead of being a member function. And checking that all the Widgets are valid is just as reasonable a thing to do:

    struct Widget {
        bool valid;
    };
    
    std::vector<Widget> widgets;
    bool all_valid = std::ranges::all_of(widgets, &Widget::valid);
    

    The only difference is that this std::invokes a pointer to member data instead of a pointer to member function. But still useful.