所以我最近有一个关于使用
std::ranges::find
算法的范围变体的问题,答案使用了投影:
if (auto const it{std::ranges::find(iv, 1, &S::a)}; it != iv.end()) {
std::cout << "Found!\n" << "\n";
}
特别是
&S::a
部分。
通常我见过在这个地方使用 lambda,但这里我们使用指向类成员的指针。这是转换为 lambda 还是正在进行一些重载选择?
有人能解释一下这个看似神奇的东西是如何工作的吗?
&S::a
是指向S
类的数据成员的指针。就像指向成员函数的指针一样,它们都可以通过特定的类对象调用,因此它们是callables。
在c++20中,
ranges
中的约束函数(位于命名空间<algorithm>
下)和<ranges>
(或大多数标准库)中的范围适配器通过std::invoke
统一调用可调用对象。
std::invoke
是用于调用可调用对象的通用接口。除了使用常见形式f(x)
调用普通函数外,它还可以处理指向数据成员/函数的指针。
让我们回到你的例子。基本上,
ranges::find
通过条件if (std::invoke(proj, *it) == value)
确定当前元素是否等于该值,其中proj
是&S::a
并且*it
返回类型为S
的对象。
因此
std::invoke(&S::a, obj_s)
返回对 a
的成员 obj_s
的引用,这是对 int
的引用。