std::all_of()的C++二元谓词版本是什么?

5
给定两个 std::vector<T>vec_avec_b,是否有标准库函数可以测试 vec_a 中的每个元素是否都小于其在位置上对应的 vec_b 元素,假设二进制运算符 operator< 对类型 T 的操作数已定义?
我认为像std::all_of的二元谓词版本会完美地完成这个任务,但我不确定它是否存在,或者如果存在的话它会被称为什么。也许将另一个执行逐元素比较的函数的输出应用于std::all_of的组合也可以起到作用,如果这样的东西存在的话。
所需功能的示例:
std::vector<int> vec_a{1, 2, 3};
std::vector<int> vec_b{2, 3, 4};

bool all_less = vec_a.size() == vec_b.size();
for (size_t i = 0; all_less && (i < vec_a.size()); ++i) {
    all_less = vec_a[i] < vec_b[i];
}

// all_less now holds desired result

你尝试过 bool all_less = vec_a.size() == vec_b.size() && vec_a < vec_b 吗? - Zereges
5
std::vector 拥有一个 operator < - PaulMcKenzie
4
针对执行词典排序比较的@Zereges,请参阅https://en.cppreference.com/w/cpp/container/vector/operator_cmp - Apollys supports Monica
2
@PaulMcKenzie 是的,它确实可以,但如果你阅读了你链接的文档,你会发现它并没有做我所要求的事情。 - Apollys supports Monica
3
或许可以使用 std::mismatch 函数。 - Zereges
啊哈!是的,尽管逻辑有点复杂。不幸的是,我认为它可能比基本方法更难阅读。 - Apollys supports Monica
4个回答

4

您可以使用std::mismatch,虽然这有点难以理解(但是它只有一行代码)

std::vector<int> vec_a{1, 2, 3};
std::vector<int> vec_b{2, 3, 4};

bool all_less = std::mismatch(vec_a.begin(), vec_a.end(), vec_b.begin(), vec_b.end(), std::less<>{}) == std::make_pair(vec_a.end(), vec_b.end());

你可以通过为容器而非范围引入一个函数来改善它。例如:
template<typename Container>
bool is_all_less(const Container& c1, const Container& c2)
{
    return std::mismatch(c1.begin(), c2.end(), c1.begin(), c2.end(), std::less<>{}) == std::make_pair(c1.end(), c2.end());
}

然后

bool all_less = is_all_less(vec_a, vec_b);

编辑

如果您确定容器的size是相同的,您也可以这样做。

bool all_less = std::mismatch(vec_a.begin(), vec_a.end(), vec_b.begin(), std::less<>{}).first == vec_a.end();

4
我不确定在任何合理的代码风格下,145个字符是否足以成为一行代码,哈哈。(但你确实找到了标准库函数来回答我的问题!) - Apollys supports Monica
@Apollys 是的,我想出了稍微更短的版本。 - Zereges

3
你正在寻找 std::equal
bool all_less = std::equal(vec_a.begin(), vec_a.end(),
                           vec_b.begin(), vec_b.end(),
                           std::less<>());
vec_b.end() 参数可以省略,如果已知向量长度相同。

0
在C++23中,有一个对n元谓词的泛化。
std::ranges::all_of(std::ranges::views::zip_transform(std::less<>{}, vec_a, vec_b), std::identity{});

0

我个人认为使用std::equal+std::less的方法更符合惯用法,因为您本质上是在询问所有对应元素对是否使用自定义相等比较函数 "equal"。

此外,mismatch的方法固有地需要按顺序处理容器,而原则上std::equal可以进行并行化。

现在,我知道您要求使用标准库的解决方案,但是Range-v3确实建立在其之上,并且下面是使用Range-v3的简洁解决方案:

// assuming these
#include <range/v3/algorithm/equal.hpp>
#include <range/v3/functional/comparisons.hpp>
using namespace ranges;

// a short oneliner
bool result = equal(vec_a, vec_b, less{});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接