Using Boost’s foreach macro

January 30, 2013
By

(This article was first published on Rcpp Gallery, and kindly contributed to R-bloggers)

Boost provides a macro, BOOST_FOREACH, that allows us to easily iterate over elements in a container, similar to what we might do in R with sapply. In particular, it frees us from having to deal with iterators as we do with std::for_each and std::transform. The macro is also compatible with the objects exposed by Rcpp.

Side note: C++11 has introduced a similar for-each looping construct of the form

for (T &elem : X) { /*do stuff*/ } 

However, CRAN does not (at the time of this posting) allow C++11 in uploads and hence this Boost solution might be preferred if you want to use a for-each construct in a package.

The BOOST_FOREACH macro is exposed when we use #include <boost/foreach.hpp>. Make sure the Boost libraries are in your includepath so that they can be found and included easily. Because it’s a header-only library we don’t have to worry about external dependencies or linking.

We’ll use a simple example where we square each element in a vector.

#include <Rcpp.h>
#include <boost/foreach.hpp>
using namespace Rcpp;
 
// the C-style upper-case macro name is a bit ugly; let's change it
// note: this could cause compiler errors if it conflicts with other includes
#define foreach BOOST_FOREACH
 
// [[Rcpp::export]]
NumericVector square( NumericVector x ) {
  
  // elem is a reference to each element in x
  // we can re-assign to these elements as well
  foreach( double& elem, x ) {
    elem = elem*elem;
  }
  
  return x;
}
square( 1:10 )
 [1]   1   4   9  16  25  36  49  64  81 100
square( matrix(1:16, nrow=4) )
     [,1] [,2] [,3] [,4]
[1,]    1   25   81  169
[2,]    4   36  100  196
[3,]    9   49  121  225
[4,]   16   64  144  256
## we check that the function handles various 'special' values
x <- c(1, 2, NA, 4, NaN, Inf, -Inf)
square(x)
[1]   1   4  NA  16 NaN Inf Inf

And a quick benchmark:

x <- rnorm(1E5)
library(microbenchmark)
microbenchmark(
  square(x),
  x^2
  )
Unit: microseconds
       expr    min     lq median     uq  max
1 square(x)  71.04  71.64  71.89  74.14 1518
2       x^2 346.36 350.70 359.18 433.33 1842
all.equal( square(x), x^2 )
[1] TRUE

If you are defining your own classes / containers and want them to be compatible with one of these for-each constructs, you will need to define some methods for iteration across these objects. See this post on SO for more details.

For more information on BOOST_FOREACH, check the documentation here.

To leave a comment for the author, please follow the link and comment on his blog: Rcpp Gallery.

R-bloggers.com offers daily e-mail updates about R news and tutorials on topics such as: visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...



If you got this far, why not subscribe for updates from the site? Choose your flavor: e-mail, twitter, RSS, or facebook...

Comments are closed.