|  | Home | Libraries | People | FAQ | More | 
      If we want to use BOOST_FOREACH to iterate over some new
      collection type, we must "teach" BOOST_FOREACH
      how to interact with our type. Since BOOST_FOREACH is built
      on top of Boost.Range, we
      must extend Boost.Range in
      order to extend BOOST_FOREACH. The section Extending
      Boost.Range explores this topic in detail.
    
      Below is an example for extending BOOST_FOREACH to iterate
      over a sub-string type, which contains two iterators into a std::string.
    
namespace my { // sub_string: part of a string, as delimited by a pair // of iterators struct sub_string { std::string::iterator begin; std::string::iterator end; /* ... implementation ... */ }; // Add overloads of range_begin() and range_end() in the // same namespace as sub_string, to be found by Argument-Dependent Lookup. inline std::string::iterator range_begin( sub_string & x ) { return x.begin; } inline std::string::iterator range_end( sub_string & x ) { return x.end; } // Also add overloads for const sub_strings. Note we use the conversion // from string::iterator to string::const_iterator here. inline std::string::const_iterator range_begin( sub_string const & x ) { return x.begin; } inline std::string::const_iterator range_end( sub_string const & x ) { return x.end; } } namespace boost { // specialize range_mutable_iterator and range_const_iterator in namespace boost template<> struct range_mutable_iterator< my::sub_string > { typedef std::string::iterator type; }; template<> struct range_const_iterator< my::sub_string > { typedef std::string::const_iterator type; }; }
      Now that we have taught Boost.Range
      (and hence BOOST_FOREACH) about our type, we can now use
      BOOST_FOREACH to iterate over our sub_string type.
    
my::sub_string substr; BOOST_FOREACH( char ch, substr ) { // Woo-hoo! }
      There are some portability issues we should be aware of when extending BOOST_FOREACH.
      Be sure to check out the Portability
      section. In particular, if your compiler does not support Argument-Dependent
      Lookup, the Boost.Range
      Portability section offers some suggested work-arounds.
    
BOOST_FOREACH Work with Non-Copyable Sequence Types
    
      For sequence types that are non-copyable, we will need to tell BOOST_FOREACH
      to not try to make copies. If our type inherits from boost::noncopyable,
      no further action is required. If not, we must specialize the boost::foreach::is_noncopyable<> template, as follows:
    
class noncopy_vector { // ... private: noncopy_vector( noncopy_vector const & ); // non-copyable! }; namespace boost { namespace foreach { template<> struct is_noncopyable< noncopy_vector > : mpl::true_ { }; }}
      Another way to achieve the same effect is to override the global boost_foreach_is_noncopyable()
      function. Doing it this way has the advantage of being portable to older compilers.
    
// At global scope... inline boost::mpl::true_ * boost_foreach_is_noncopyable( noncopy_vector *&, boost::foreach::tag ) { return 0; }
| ![[Tip]](../../../doc/src/images/tip.png) | Tip | 
|---|---|
| 
        Even though we have to tell  | 
BOOST_FOREACH for Lightweight Proxy Sequence Types
    
      On some compilers, BOOST_FOREACH must occasionally take
      a slightly slower code path to guarantee correct handling of sequences stored
      in temporary objects. It asks itself, "Should I make a copy of this object?"
      and later, "Did I make a copy or not?" For some types of sequences,
      this is overkill. Consider a sequence which is a simple pair of iterators.
      Jumping through hoops of fire to avoid copying it doesn't make sense because
      copying it is so cheap.
    
      A pair of iterators is an example of a lightweight proxy. It does not store
      the values of the sequence; rather, it stores iterators to them. This means
      that iterating over a copy of the proxy object will give the same results as
      using the object itself. For such types, BOOST_FOREACH provides
      a hook that lets us tell it not to worry about the expense of making a copy.
      This can result in slightly faster loop execution. Simply specialize the boost::foreach::is_lightweight_proxy<> trait, as follows:
    
struct sub_string : boost::iterator_range< std::string::iterator > { // ... }; namespace boost { namespace foreach { template<> struct is_lightweight_proxy< sub_string > : mpl::true_ { }; }}
      Alternately, we could achieve the same effect by overriding the global boost_foreach_is_lightweight_proxy()
      function, as follows:
    
// At global scope... inline boost::mpl::true_ * boost_foreach_is_lightweight_proxy( sub_string *&, boost::foreach::tag ) { return 0; }
This method is portable to older compilers.