How to make my class iterable by BOOST_FOREACH in C++?

844 views Asked by At

EDIT: I give up! I am using simply for (string& word : sentence) { .. } instead now. BOOST_FOREACH is hopeless. Thank you.

I've read this, and this, and they did not help at all. Especially I want to ask about the second link. Why do you have to define some strange structs under the namespace boost? The class that I want to enable BOOST_FOREACH for is defined in my own namespace. How can I access data from that class if I define my iterators in namespace boost { .. }? This makes no sense. I don't know why finding the equivalence of IEnumerable in C++ took me so much time! Wans't boost supposed to save my time?

Could anybody just tell me the neatest way to iterate over this class:

class Sentence {
private:
    vector<string> words;
}

with this code:

Sentence sentence;
BOOST_FOREACH(string word, sentence) {
    // ..
}

Thanks.

1

There are 1 answers

2
juanchopanza On

According to the documentation, anything that looks like a standard library container would work. The simplest way would be to expose a pair of iterators in your class. If you do not want to implement your own, simply use vector<string> iterators:

class Sentence 
{
public:
  typedef vector<string>::iterator iterator;
  typedef vector<string>::const_iterator const_iterator;
  const_iterator begin() const { return words.begin(); }
  const_iterator end() const { return words.end(); }
private:
    vector<string> words;
};

Edit it seems BOOST_FOREACH is not clever enough to understand standard library container-like types, but it can understand a pair of standard library iterators. So an extra step is required:

#include <iostream>
#include <utility>
int main()
{
  Sentence sentence;
  auto s = std::make_pair(sentence.begin(), sentence.end());
  BOOST_FOREACH(std::string word, s) {
    std::cout << word << std::endl;
  }
}

Note 1: You may want to de-couple the explicit type of the iterator using type erasure, but that could be seen as a refinement. See this relevant discussion for more information.

Note 2: I was never a big fan of BOOST_FOREACH. C++11 range based loops make it even less likely that I would use it in real code.