2

These questions have got me curious about the purpose of Boost and Qt's for each macros.

I've used Qt's and find the macro has always worked well enough for my needs but have never extensively tested its performance. I have not used Boost's offering before.

What I would like to know is when would be a good time to use the alternatives provided by Qt and Boost over std::for_each?

Note: The wording has been changed from the original to make the question more objective.

Community
  • 1
  • 1
Samuel Harmer
  • 4,264
  • 5
  • 33
  • 67
  • 4
    `std::for_each` has existed since at least C++98, so I'd be amazed if you found a compiler that _didn't_ support it. That being said, what you're asking for is essentially subjective, and thus not a good question for SO. – ildjarn May 09 '12 at 21:58
  • 1
    How can one offer a pro or con without giving one's opinion, which is subjective by definition? – ildjarn May 09 '12 at 22:01
  • You have the links to the documentation. The documentation describes what the functions do. Can you not derive the differences by comparing the descriptions? – Benjamin Lindley May 09 '12 at 22:06
  • 5
    In some cases you may not have to pay for parking with a car either, so no, we do not agree. The bottom line is that [Stack Overflow is not a List for All Things](http://meta.stackexchange.com/a/128561/166663), [nor is it a Recommendation Engine](http://meta.stackexchange.com/a/128562/166663), [nor is it your personal research assistant](http://meta.stackexchange.com/a/128553/166663) -- there's just no way this question fits here IMO. – ildjarn May 09 '12 at 22:14
  • I have to pay for parking, but its only $1.25 rather than $2.00. – John Dibling May 09 '12 at 22:15
  • "And secondly, what are the differences, and (quantifiable) pros, and cons for each of the following?" All three come with source code. Read source, and differences, cons/pros should become fairly obvious – SigTerm May 09 '12 at 22:21
  • I'm not saying your question doesn't make sense, or that it's a bad question in any way; I'm only saying it isn't a good fit for SO. :-] You may want to try [Programmers.SE](http://programmers.stackexchange.com). – ildjarn May 09 '12 at 22:29
  • 1
    @ildjarn: I doubt PSE is the right place either -- they are not our dumping ground. I don't think there's anywhere on SE where this question is not going to get closed. – John Dibling May 09 '12 at 22:31
  • That just means you're fundamentally misunderstanding SO's format. – ildjarn May 09 '12 at 22:42
  • How about using the new C++11 ranged for-loop, it is the easiest and best to work with and it is *standard* – Yet Another Geek May 10 '12 at 21:02
  • @Yet: Because, while it is a standard feature of the language, C++11 is not *everywhere*. You have to have a compiler version that supports this construct, and quite a few widely used ones do not. – Nicol Bolas May 10 '12 at 21:03
  • @NicolBolas As far as I can see the latest version of the three major compilers (VC++, GCC and Clang) all support range-based for-loops. If one can use it, it can well be preferred over any stl based implementation or non-standard implementation. – Yet Another Geek May 10 '12 at 21:05
  • @Yet: Consider that the latest version of one of those compilers is still in *beta*. And yes, while it would be preferred where possible, that doesn't mean it is in fact possible. – Nicol Bolas May 10 '12 at 21:09

3 Answers3

5

The purpose and functioning of std::for_each is very different from that of the macros BOOST_FOREACH and Q_FOREACH.

std::for_each is, first and foremost, a function call. It is an algorithm. You call it, providing a pair of iterators. On each member of the iterator range, it will call the given function with the value fetched from the iterator in question.

The purpose of std::for_each, conceptually speaking, is really to match up with the more specific algorithms that already exist. With algorithms like count, copy, etc, it makes sense to have one that simply executes arbitrary code for every element.

BOOST_FOREACH and Q_FOREACH are equivalent constructs (which I will collectively call FOREACH), but behave differently from std::for_each.

FOREACH is, first and foremost, a for loop. Now, that might not sound so different, but think about it. You cannot call continue and break from within std::for_each. continue can be emulated easily enough with return (though this also means you can't return from the function that issues the std::for_each call). But there's no way to escape from the std::for_each loop if you want to stop. Similarly, you can't goto out of a for_each loop. The best you can do in either case is throw an exception, and that's using exceptions for flow control (ie: not a good idea).

When you use std::for_each, you must provide some callable function. This could be a function pointer or function object. Because of that, your code is somewhat de-localized. This is fine if what you're doing in each iteration is a complex, multi-line function. But if each iteration's logic is quite simple, then code readability decreases a bit.

FOREACH executes a local block of code. So the code is right there; you don't have to track down a function to see what's happening on each iteration.

Also, calling a function means having to write that function. If you need to keep track of state, you now need a functor, which requires more code to write.

C++11 makes std::for_each much more attractive with lambda functions. This removes the code locality problem: the source code is right there. And since lambdas can capture stuff, it can work almost exactly like a regular for loop. Well, except for no break functionality, but that's usually avoidable.

Of course, C++11 also makes it effectively obsolete (along with FOREACH) with range-based for loops. But since there are different levels of conformance with C++11, there are some environments where you have lambda but not range-based for.

What you ought to use is up to you. FOREACH is nice, and if you're already using Boost and/or Qt, then feel free. But I wouldn't suddenly start using these just for FOREACH. Personally, I wouldn't use std::for_each unless you're also using lambdas or something, due to code locality issues. Just use a for loop.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
1

std::for_each is part of the C++ Standard, and has been since 1998 (at least). Hence any (not-so) modern C++ is non-compliant and therefore broken if it doesn't provide for_each. All compilers I use on a daily basis support it.

Both of the libraries you mention live outside the C++ language itself. for_each is the only one that is guaranteed to be present in a conformant compiler.

As for pros and cons, I leave that to you to decide. Given a choice, I'll go with something guaranteed by the Standard over something that's not.

John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • is for_each faster in terms of speed than the normal looping mechanisms ? – Jay D May 09 '12 at 22:21
  • The Standard says it runs in O(n) time. In every implementation I've seen, it's just a for loop that is at least as fast as anything you could write in a general sense. – John Dibling May 09 '12 at 22:23
  • 4
    That being said, *speed of execution* is neither a typical reason to use `for_each`, nor is it a reason not to. – John Dibling May 09 '12 at 22:24
  • my question was not about time complexity any looping(for, for_each, while) would work in O(n). my question was are there overheads in using for_each than using standard for. THanks. – Jay D May 09 '12 at 22:32
  • 1
    It's an `inline` function call. All else is implementation-defined but, as I said, I've never seen an implementation that is worse than hand-written code. I suggest you take a look at *your* implementation if this is a major concern. – John Dibling May 09 '12 at 22:38
1

std::for_each requires a functor, lambda or function-pointer to execute. Using it you can avoid a lot of boilerplate if you loop the same methods at several places in your code.

 void hello(int i){
      printf("World %d \n",i);
 }

 std::vector<int> vals;
 vals.push_back(1);
 vals.push_back(2);
 std::for_each(vals.begin(),vals.end(),hello);

BOOST_FOREACH and Q_FOREACH are used to hide the boilerplate of c++ iterators, they replace the normal for-statement and loop over the loop body.

  for(vector<int>::iterator iter = vals.begin();iter != vals.end();++iter)
  {
      hello(*iter);
  }

  Q_FOREACH(int val, vals){
      hello(val);
  }

Usage: Which ever you think is most readable and avoids unnecessary code duplication.

Performance: every one of these is either a macro or a template function and completely visible to the compiler, differences should only exist in debug builds if at all.

josefx
  • 15,506
  • 6
  • 38
  • 63