Boost logo

Boost :

From: Matthew Vogt (mvogt_at_[hidden])
Date: 2004-04-23 00:11:06


Like the following:

I guess it depends on how much you're willing to pay for syntactic sugar...

//-----------------------------------------------------------------------------

#include <iostream>
#include <vector>
#include <deque>
#include <list>
#include <utility>

#include "each.hpp"

template<typename T1, typename T2>
std::ostream& operator<< (std::ostream& os, const std::pair<T1, T2>& p)
{
  return os << "{" << p.first << "," << p.second << "}";
}

int main(int, char**)
{
  std::vector<int> int_vector;
  int_vector.push_back(5);
  int_vector.push_back(10);

  for (each<int> in(int_vector); in; ++in)
    std::cout << *in << std::endl;

  std::deque<double> double_deque;
  double_deque.push_back(3.14);
  double_deque.push_front(99.999);

  for (each<double> in(double_deque); in; ++in)
    std::cout << *in << std::endl;

  std::list<std::pair<unsigned, char> > pair_list;
  pair_list.push_back(std::make_pair(10, 'a'+13));
  pair_list.push_back(std::make_pair(11, 'a'+14));

  for (each<std::pair<unsigned, char> > in(pair_list); in; ++in)
    std::cout << *in << std::endl;

  std::list<int> int_list(3);
  for (each<int> in(int_list); in; ++in)
    *in = 5;
  for (each<const int> in(int_list); in; ++in)
    std::cout << *in << std::endl;

  return 0;
}

//-- each.hpp -----------------------------------------------------------------

#include <boost/function.hpp>
#include <boost/bind.hpp>

template<typename T>
struct each
{
  typedef T value_type;

  template<typename ContainerType>
  each(ContainerType& c) : iter(c.begin(), c.end()) {}

  operator bool(void) const { return iter.at_end() == false; }

  void operator++(void) { iter.increment(); }

  value_type& operator*(void) const { return iter.dereference(); }

private:
  struct iterator_wrapper
  {
    struct iterator_storage
    {
      // Allocate a memory buffer sized to hold a real iterator, and copy it
      template<typename BaseIteratorType>
      iterator_storage(const BaseIteratorType& t) :
        address(operator new(sizeof t))
      {
        BaseIteratorType* typed_address =
          reinterpret_cast<BaseIteratorType*>(address);
        *typed_address = t;
      }

      ~iterator_storage() { operator delete(address); }

      void* address;
    };

    template<typename IteratorType>
    iterator_wrapper(IteratorType begin, IteratorType end) :
      current_storage(begin),
      end_storage(end)
    {
      // Make bound references to the operations we need, on the iterator copy
      IteratorType* saved_begin =
        reinterpret_cast<IteratorType*>(current_storage.address);
      increment = boost::bind(&IteratorType::operator++, saved_begin);
      dereference = boost::bind(&IteratorType::operator*, saved_begin);

      IteratorType* saved_end =
        reinterpret_cast<IteratorType*>(end_storage.address);
      at_end = boost::bind(&iterator_wrapper::is_equal<IteratorType>,
                           saved_begin,
                           saved_end);
    }

    template<typename IteratorType>
    static bool is_equal(const IteratorType* first, const IteratorType* second)
    {
      return (*first == *second);
    }

    boost::function<void (void)> increment;
    boost::function<value_type& (void)> dereference;
    boost::function<bool (void)> at_end;

    iterator_storage current_storage;
    iterator_storage end_storage;
  };

  iterator_wrapper iter;
};


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk