Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do class members behave like functions when used as projections?

So I recently had a question about using the ranges variant of the std::ranges::find algorithm and the answer used a projection:

if (auto const it{std::ranges::find(iv, 1, &S::a)}; it != iv.end()) {
    std::cout << "Found!\n" << "\n";
}

Specifically the &S::a part. Normally I have seen a lambda being used in this place, but here we use a pointer to a class member. Is this transformed into a lambda or is there some overload selection going on?

Can someone break down how this, seemingly magic, works?

like image 921
SupAl Avatar asked Jan 28 '26 21:01

SupAl


1 Answers

&S::a is a pointer to the data member of class S. Just like pointers to member functions, they both can be invoked through specific class objects, so they are callables.

In c++20, constraint functions (which are under namespace ranges) in <algorithm> and range adaptors in <ranges> (or most of the standard library) uniformly invoke callables through std::invoke.

std::invoke is a generalized interface for calling callables. In addition to calling ordinary functions with the common form of f(x), it can also handle pointers to data members/functions.

Let's go back to your example. Basically, ranges::find determines whether the current element is equal to the value via the condition if (std::invoke(proj, *it) == value), where proj is &S::a and *it returns an object of type S.

So std::invoke(&S::a, obj_s) returns a reference to the member a of the obj_s, which is a reference to an int.

like image 152
康桓瑋 Avatar answered Jan 30 '26 11:01

康桓瑋



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!