有类似于 "std::and" 或 "std::or" 的东西吗?

27

给定一个布尔值容器(例如std::vector<bool>),是否有一种标准函数可以返回true,如果所有值都为true(“和”),或者如果至少一个值为true则返回true(“或”),并进行短路计算?

我今天早上查看了www.cplusplus.com,但没有找到类似的函数。


9
确实如此。但即使代码很简单,如果已经存在相应的东西,为什么要重写呢? - ereOn
5
@Dani Nonsense. 查看 <algorithm><functional>,其中有许多方便的函数和类,它们的实现是微不足道的。 - Konrad Rudolph
2
@Dani:写一些琐碎的东西并不能引以为豪。不冒犯你,但是你的评论让我想起了我工作中的一个人,他拒绝使用共享指针和std::string,因为他知道如何自己实现它们。当然,他确实知道,但结果是他的代码经常难以维护,并且充斥着琐碎的技巧。 - ereOn
4
@Dani: 所以最终我将得到一个由我维护的可内联的一行函数,而不是由构建我的编译器的人维护的一行函数。下一步是什么?重写自己的 memcpystd :: copy 吗?毕竟,这只是一个单独的 for 循环。 - ereOn
4
好的,我会尽力为您翻译。以下是需要翻译的内容:@Dani: 好的一点是,因为C++0x 包括std::all_ofstd::any_of函数,所以肯定有很多人“像我一样”。此外,如果这些简单的函数可以进行内联(它们肯定可以),那么与“编写自己版本的这些函数”相比,它们会带来什么样的大小差异呢? - ereOn
显示剩余9条评论
4个回答

52

是否有一个标准函数,如果所有值为true("and"),则返回true

std::all_of(vec.begin(), vec.end(), [](bool x) { return x; } )
或者在至少一个值为真时返回true("或")。
std::any_of(vec.begin(), vec.end(), [](bool x) { return x; } )

使用短路求值吗?

我只是在 lambda 中插入了打印语句,是的,两个函数都执行了短路求值。


+1. 我知道这一天会到来。不幸的是,我现在无法在我的项目中使用C++0x,但这很好知道。谢谢。 - ereOn
1
@ereOn:我也一样(在工作中无法这样做),所以我继续创建了它们(当然不是在std命名空间中),以帮助未来的迁移 :) - Matthieu M.
正如@Morwenn所说,缺少一元谓词。 - Hanna Khalil
@HannaKhalil 感谢您的反馈,我刚刚更新了我的答案! - fredoverflow

42
你可以这样实现:
AND:
std::find(vector.begin(), vector.end(), false) == vector.end() // all the values are true

或者:

std::find(vector.begin(), vector.end(), true) != vector.end() //at least one value is true

1
有时候我想可能是我搜索得太努力了...如果我需要对值执行更复杂的检查,我甚至可以使用函数对象来使用find_if。非常感谢! - ereOn
我接受了FredOverflow的答案,因为他的解决方案更加直观。点赞这个答案是为了公正,也因为它非常聪明。 - ereOn
1
@ereOn:但是你说你不能使用Fred的答案作为你的解决方案。 - Lightness Races in Orbit
@Tomalak:确实。 我现在无法使用它,但似乎仍然被推荐作为此操作的建议方式。 我实际上已经实现了这两个解决方案,并将其中一个注释掉,直到可以使用它。 - ereOn
2
@ereOn:如果你使用的是C++0x,我建议你使用这个。但在关键的生产代码中,我不会使用非标准特性。如果你想要一个标准的C++解决方案——而且,顺便说一句,这个解决方案实际上适用于你ereOn——那么这就是目前针对所述问题的正确答案。未来的标准使它变得更容易是一个有趣的旁注。 - Lightness Races in Orbit

12
您可以使用函数对象 logical_andlogical_or 与 reduction 结合使用来实现这一点。 accumulate 计算 reduction,因此:
bool any = std::accumulate(foo.begin(), foo.end(), false, std::logical_or<>());
bool all = std::accumulate(foo.begin(), foo.end(), true, std::logical_and<>());

注意:这里没有使用短路(accumulate函数对于短路一无所知,尽管函数对象是有的),而Igor的巧妙解决方案使用了短路。


1
std::accumulate 用于归约,怎么样? - ltjax
4
这是否使用短路求值规则? - Arafangion
FYI 这个无法编译。 - Timon Knigge

1

如果您不需要针对不同容器类型的通用算法...

由于您正在寻找短路评估,您可以尝试使用std::valarray。 对于and,请使用valarray :: min()== true,对于or,您可以使用Igor提到的std :: find

如果您在编译时知道要存储的元素数量,甚至可以使用std :: bitset:

bitset<100> container();

//... fill bitset

bool or = container.any();
bool and = container.count() == container.size();

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