为什么`std :: all_of`不使用`std :: invoke`?

时间:2019-10-14 17:13:11

标签: c++ stl c++17

在类似的问题(例如here)中已指出,您不能将类方法指针作为std::all_of的谓词。

但是,在C ++ 17中,我们有std::invoke,它可以使std::all_of和类似的函数更容易接受成员函数(甚至成员变量)指针。

更具体地说,以下内容无法在GCC 9.2上编译:

#include <algorithm>
#include <vector>

struct S {
    bool check() const { return true; }
};

int main() {
    std::vector<S> vs;
    std::all_of(vs.begin(), vs.end(), &S::check);
}

Godbolt link包含一些示例代码和使用调用的all_of的玩具版本。

为什么有此限制?我想念什么吗?我以为std::invoke标准化后,它也应该应用于适当的STL函数。

2 个答案:

答案 0 :(得分:5)

原因1:没有人提出过建议。 P0312R1提议使指针到成员函数的语言可调用,但遭到拒绝(对此达成共识)

原因2:使用lambda(以及之前的std::bind),动力很小。如果S是标准定义类型(例如vector),则基于其他原因,成员到指针选项将是非法的。

std::all_of(vs.begin(), vs.end(), [](auto const& s) {return s.check();});

答案 1 :(得分:4)

下一代算法(std::ranges名称空间中的那些算法)完全按照您的建议(https://godbolt.org/z/uaPoJf)接受用std::invoke调用的谓词:

std::ranges::all_of(vs.begin(), vs.end(), &S::check);

或更短(https://godbolt.org/z/_qiO8G):

std::ranges::all_of(vs, &S::check);

此外,它们接受一个称为“投影”的附加参数,该参数是传递给算法的一元转换函数,该算法在对元素进行运算之前已应用于每个元素。例如(https://godbolt.org/z/gWY-OR):

std::ranges::all_of(vs, std::logical_not(), &S::check);

您已经可以将以上所有内容与Casey Carter的cmcstl2或Eric Niebler的range-v3结合使用。