Is there anything like "std::and" or "std::or"?
Asked Answered
H

4

28

Given a container of boolean values (An example is std::vector<bool>), is there a standard function that returns true if all the values are true ("and") or true if at least one value is true ("or"), with short circuit evalutation ?

I digged trough www.cplusplus.com this morning but couldn't find anything close.

Hokku answered 28/6, 2011 at 12:48 Comment(14)
You can easily implement your own...Swatch
@Dani: Indeed. But even if the code is trivial, if there is anything that already exists, why would I rewrite it ?Hokku
@ereOn, things that are easily implemented don't go into c++. if you want that try c# or even some interpreter.Swatch
@Dani Nonsense. See <algorithm> and <functional> for tons of convenience functions and classes whose implementation is trivial.Salzburg
@Dani: There is no pride to get from writing something trivial. No offense, but your comment reminds me of a guy at my work that refuses to use shared pointers and std::string because he knows how to do that himself. Sure he does, but as a result his code is often unmaintainable and cluttered with trivial tricks.Hokku
Did you look at the size of std::string? its huge, not trivial. however, 3 line for, is.Swatch
cplusplus.com is a poor resource.Ancillary
@Dani: std::string is "huge"?Ancillary
string after concating its different files is 15312 linesSwatch
@Dani: Repeat those 3 lines one hundred times and compare it to what you would have got using one of the "one-liners" below: you just lost 200 hundred lines of trivial code that brings nothing.Hokku
@ereOn, you can say it for pretty much everything... and if you excessively use this in your application just make an inlined function/macro for itSwatch
@Dani: So I would end up with a one-line, inlinable function maintained by me in place of a... one-line, inlinable function maintained by the people who built my compiler. What is the next step ? Rewriting my own memcpy or std::copy ? After all, it is just a single for loop.Hokku
I don't know about std::copy, but memcpy uses some processor specific instructions which make it faster... and what I meant is that the c++ library will just become more bloated when people like you ask for features that you can use for yourself. a simple static hello world is already few kilobytes when all it does is write 1 line to the screen.Swatch
@Dani: The good thing is that there must be a lot of people "like me" since C++0x includes std::all_of and std::any_of :) Moreover, if these simple functions are inlinable (which they surely are), what size difference with "rolling out my own version of these functions" does it make anyway ?Hokku
G
43

You can implement by:

AND:

std::find(vector.begin(), vector.end(), false) == vector.end() // all the values are true

OR:

std::find(vector.begin(), vector.end(), true) != vector.end() //at least one value is true
Gayle answered 28/6, 2011 at 12:52 Comment(5)
Well sometimes I guess I'm searching too hard... And I can even use find_if with a function object if I need to perform a more complicated check on the values. Thank you very much !Hokku
I accepted FredOverflow's answer because his solution is more straightforward. Upvoted this one for fairness and because it is really clever.Hokku
@ereOn: But you said that you can't use Fred's answer as your solution.Ancillary
@Tomalak: Indeed. I can't use it right now, but it still seems to be the recommended way to do this. I actually implemented the two solutions and commented out one of them until I can use it.Hokku
@ereOn: Recommended if you have C++0x. I won't use non-standard features in critical production code, though. If you want a standard C++ solution -- and, incidentally, one that actually works for you ereOn -- then this is the correct answer, at present, to the stated problem. That a future standard makes it a bit easier is an interesting sidenote.Ancillary
E
53

is there a standard function that returns true if all the values are true ("and")

std::all_of(vec.begin(), vec.end(), [](bool x) { return x; } )

or true if at least one value is true ("or")

std::any_of(vec.begin(), vec.end(), [](bool x) { return x; } )

with short circuit evalutation?

I just inserted print statements into the lambda, and yes, both functions perform short-circuiting.

Earthiness answered 28/6, 2011 at 12:55 Comment(4)
+1. I knew this would be added some day. I unfortunately cannot use C++0x right now on my project, but that's good to know. Thank you.Hokku
@ereOn: neither can I (at work), so I went ahead and created them (not in the namespace std, of course) to help with future migration :)Starr
as @Morwenn said there is missing Unary PredicateAbeyance
@HannaKhalil Thanks for the feedback, I just updated my answer!Earthiness
G
43

You can implement by:

AND:

std::find(vector.begin(), vector.end(), false) == vector.end() // all the values are true

OR:

std::find(vector.begin(), vector.end(), true) != vector.end() //at least one value is true
Gayle answered 28/6, 2011 at 12:52 Comment(5)
Well sometimes I guess I'm searching too hard... And I can even use find_if with a function object if I need to perform a more complicated check on the values. Thank you very much !Hokku
I accepted FredOverflow's answer because his solution is more straightforward. Upvoted this one for fairness and because it is really clever.Hokku
@ereOn: But you said that you can't use Fred's answer as your solution.Ancillary
@Tomalak: Indeed. I can't use it right now, but it still seems to be the recommended way to do this. I actually implemented the two solutions and commented out one of them until I can use it.Hokku
@ereOn: Recommended if you have C++0x. I won't use non-standard features in critical production code, though. If you want a standard C++ solution -- and, incidentally, one that actually works for you ereOn -- then this is the correct answer, at present, to the stated problem. That a future standard makes it a bit easier is an interesting sidenote.Ancillary
S
13

You can use the function objects logical_and and logical_or in conjunction with a reduction to accomplish that.

accumulate calculates the reduction. Hence:

bool any = std::accumulate(foo.begin(), foo.end(), false, std::logical_or<>());
bool all = std::accumulate(foo.begin(), foo.end(), true, std::logical_and<>());

Caveat: this is not using short-circuiting (the accumulate function knows nothing about short-circuiting even though the functors do), while Igor’s clever solution is.

Salzburg answered 28/6, 2011 at 12:53 Comment(3)
How about std::accumulate for reduction?Mareld
Is this using short-circuit evalutation rules?Marisolmarissa
FYI this does not compileAdministrate
A
2

If you do not need a generic algorithm for different container types...

As you are looking for short circuit evaluation, you may give std::valarray a chance. For and use valarray::min() == true for or you could use std::find as mentioned by Igor.

In case you know the number of elements to store at compile time, you could even use a std::bitset:

bitset<100> container();

//... fill bitset

bool or = container.any();
bool and = container.count() == container.size();
Agony answered 28/6, 2011 at 13:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.