3

I have a std::deque< std::pair<int, int> > that I would like to iterate over using BOOST_FOREACH.

I tried the following:

  #define foreach_ BOOST_FOREACH

  // declaration of the std::deque
  std::deque< std::pair<int, int> > chosen;

  foreach_( std::pair<int,int> p, chosen )
  {
     ... 
  }

But when I compile this (in Visual Studio ) I get the following errors:

warning C4002: too many actual parameters for macro 'BOOST_FOREACH'
1>c:\users\beeband\tests.cpp(133): error C2143: syntax error : missing ')' before '>'
1>c:\users\beeband\tests.cpp(133): error C2059: syntax error : '>'
1>c:\users\beeband\tests.cpp(133): error C2059: syntax error : ')'
1>c:\users\beeband\tests.cpp(133): error C2143: syntax error : missing ';' before '{'
1>c:\users\beeband\tests.cpp(133): error C2181: illegal else without matching if

What is the correct way to use BOOST_FOREACH with this deque?

hmjd
  • 113,589
  • 17
  • 194
  • 245
BeeBand
  • 9,539
  • 19
  • 56
  • 83
  • 2
    [Related question](http://stackoverflow.com/questions/8942912/how-to-pass-multi-argument-templates-to-macros), see answers there – gx_ Jul 04 '13 at 10:21

3 Answers3

7

The problem is the , as it is being used by the preprocessor to separate the macro arguments.

Possible solutions using typedef:

typedef std::pair<int, int> int_pair_t;
std::deque<int_pair_t> chosen;
foreach_( int_pair_t p, chosen )

// Or (as commented by Arne Mertz)
typedef std::deque<std::pair<int, int>> container_t;
container_t chosen;
foreach_(container_t::value_type p, chosen)

Possible replacements, both introduced in c++11, are:

  • range-for loop:

    for (auto& : chosen)
    {
    }
    
  • lambdas:

    std::for_each(std::begin(chosen),
                  std::end(chosen)
                  [](std::pair<int, int>& p)
                  {
                  });
    
hmjd
  • 113,589
  • 17
  • 194
  • 245
  • 1
    Another typedef solution would be to typedef the container and then use `Cont::value_type`. That way you'll have to change only one place if you change the containerelements, e.g. to `std::pair` – Arne Mertz Jul 04 '13 at 10:32
6

As the author of BOOST_FOREACH, I ask you to please stop using it. It was a hack whose time has come and gone. Please, please, please use C++11's range-base for loops and let BOOST_FOREACH die.

Eric Niebler
  • 5,315
  • 1
  • 24
  • 37
4

Boosts foreach is a macro, which means it's handled by the preprocessor. And the preprocessor is pretty simple, and can't handle symbols with commas in them as it is used as a macro argument separator.

Some programmer dude
  • 363,249
  • 31
  • 351
  • 550