In this so question about sorting only some fields in a std::vector of struct, this interesting answer was provided:
std::vector<SimpleStruct> vs = {{1, 10, 11}, {5, 100, 111}, {3, 1000, 1111}};
std::ranges::sort(vs | std::views::transform(&SimpleStruct::a));
// vs now becomes {1, 10, 11}, {3, 100, 111}, {5, 1000, 1111}
The goal, I get, is to emulate a view that would act as a std::vector of only the field a.
Yet, I don't get how std::views:transform can use a pointer to data member as a transformation function. As far as I understand the documentation it should be passed a callable object.
Why and how is it working as expected (I probably missed an important detail in cppreference).
std::invoke(object, &Class::member)and getobject.memberback). It's a weird, but useful quirk in the language. Side note: this could also be spelled with a projection -std::ranges::sort(vs, {}, &SimpleStruct::a)INVOKEthat can take a function and its arguments and call that function. And this imaginaryINVOKEwas defined to also be able to accept pointers to data members. Since C++17 we have a real implementation ofINVOKE-std::invoke.ranges::sort; the algorithm still swaps the complete elements. But this particular case really only wants to swap the members. For this reason, the variant with the projection cannot be used.