実装と試験用コード

VC7.1 と GCC3.4.2 (MinGW) でコンパイルと動作を確認.

#include <boost/config.hpp>
#include <boost/range/result_iterator.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>

#if !defined(CRY_FOREACH_MAX_COUNT)
#define CRY_FOREACH_MAX_COUNT 100
#endif

#define CRY_FOREACH_AUTO_RANGE_MAX_COUNT CRY_FOREACH_MAX_COUNT

#define CRY_FOREACH_AUTO_ITERATOR_MAX_COUNT CRY_FOREACH_MAX_COUNT


namespace cry{

namespace foreach_detail{

template<int n>
struct auto_range_count_tag
  : public auto_range_count_tag<n - 1>
{};

template<>
struct auto_range_count_tag<1>
{};

struct auto_range_end_of_count_tag
  : public auto_range_count_tag< CRY_FOREACH_AUTO_RANGE_MAX_COUNT >
{};

char (&test_auto_range_count(auto_range_count_tag<1>))[1];

template<int n>
struct test_auto_range_count_injector
{
  friend char (&test_auto_range_count(auto_range_count_tag<n>))[n];
};

#define CRY_FOREACH_AUTO_RANGE_COUNT()                   \
sizeof(                                                  \
  ::cry::foreach_detail::test_auto_range_count(          \
    ::cry::foreach_detail::auto_range_end_of_count_tag() \
  )                                                      \
)

#define CRY_FOREACH_INCREMENT_AUTO_RANGE_COUNT()         \
sizeof(                                                  \
  ::cry::foreach_detail::test_auto_range_count_injector< \
    CRY_FOREACH_AUTO_RANGE_COUNT() + 1                   \
  >                                                      \
), 0



template<int n>
struct auto_iterator_count_tag
  : public auto_iterator_count_tag<n - 1>
{};

template<>
struct auto_iterator_count_tag<1>
{};

struct auto_iterator_end_of_count_tag
  : public auto_iterator_count_tag< CRY_FOREACH_AUTO_ITERATOR_MAX_COUNT >
{};

char (&test_auto_iterator_count(auto_iterator_count_tag<1>))[1];

template<int n>
struct test_auto_iterator_count_injector
{
  friend char (&test_auto_iterator_count(auto_iterator_count_tag<n>))[n];
};

#define CRY_FOREACH_AUTO_ITERATOR_COUNT()                   \
sizeof(                                                     \
  ::cry::foreach_detail::test_auto_iterator_count(          \
    ::cry::foreach_detail::auto_iterator_end_of_count_tag() \
  )                                                         \
)

#define CRY_FOREACH_INCREMENT_AUTO_ITERATOR_COUNT()         \
sizeof(                                                     \
  ::cry::foreach_detail::test_auto_iterator_count_injector< \
    CRY_FOREACH_AUTO_ITERATOR_COUNT() + 1                   \
  >                                                         \
), 0



template<int id>
struct auto_range_base
{
  operator bool() const
  {
    return false;
  }
};

template<int id, class Iterator>
class auto_range
  : public auto_range_base<id>
{
public:
  auto_range(Iterator const &first, Iterator const &last)
    : first_(first)
    , last_(last)
  {}

  friend
  Iterator cry_foreach_auto_range_begin(
    auto_range_base<id> const &r
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
  , auto_range * = 0
#endif
  )
  {
    return static_cast<auto_range const &>(r).first_;
  }

  friend
  Iterator cry_foreach_auto_range_end(
    auto_range_base<id> const &r
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
  , auto_range * = 0
#endif
  )
  {
    return static_cast<auto_range const &>(r).last_;
  }

private:
  Iterator first_;
  Iterator last_;
}; // class auto_range

template<int id, class Iterator>
auto_range<id, Iterator>
make_auto_range_impl(Iterator const &first, Iterator const &last)
{
  return auto_range<id, Iterator>(first, last);
}

template<int id, class Range>
auto_range<id, typename boost::range_result_iterator<Range>::type>
make_auto_range(Range &r)
{
  return make_auto_range_impl<id>(boost::begin(r), boost::end(r));
}

template<int id, class Range>
auto_range<id, typename boost::range_const_iterator<Range>::type>
make_auto_range(Range const &r)
{
  return make_auto_range_impl<id>(boost::begin(r), boost::end(r));
}



template<int id>
struct auto_iterator_base
{
  operator bool() const
  {
    return false;
  }
};

template<int id, class Iterator>
class auto_iterator
  : public auto_iterator_base<id>
{
public:
  typedef typename boost::iterator_reference<Iterator>::type reference;
  
  auto_iterator(Iterator const &it)
    : it_(it)
  {}
  
  friend reference deref(
    auto_iterator_base<id> const &x
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
  , auto_iterator * = 0
#endif
  )
  {
    return *static_cast<auto_iterator const &>(x).it_;
  }

  friend bool cry_foreach_auto_iterator_equal_to(
    auto_iterator_base<id> const &x
  , auto_iterator_base<id> const &y
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
  , auto_iterator * = 0
#endif
  )
  {
    return static_cast<auto_iterator const &>(x).it_
        == static_cast<auto_iterator const &>(y).it_;
  }

  friend void cry_foreach_auto_iterator_increment(
    auto_iterator_base<id> const &x
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
  , auto_iterator * = 0
#endif
  )
  {
    ++static_cast<auto_iterator const &>(x).it_;
  }
  
private:
  mutable Iterator it_;
}; // class auto_iterator

template<int id, class Iterator>
auto_iterator<id, Iterator> make_auto_iterator(Iterator const &x)
{
  return auto_iterator<id, Iterator>(x);
}

} // namespace foreach_detail

} // namespace cry



#define CRY_FOREACH_AUTO_RANGE(NAME, EXPRESSION) \
::cry::foreach_detail::auto_range_base<          \
  CRY_FOREACH_AUTO_RANGE_COUNT()                 \
> const &NAME                                    \
= ::cry::foreach_detail::make_auto_range<        \
  CRY_FOREACH_AUTO_RANGE_COUNT()                 \
>(EXPRESSION)



#define CRY_FOREACH_AUTO_ITERATOR(NAME, EXPRESSION) \
::cry::foreach_detail::auto_iterator_base<          \
  CRY_FOREACH_AUTO_ITERATOR_COUNT()                 \
> const &NAME                                       \
= ::cry::foreach_detail::make_auto_iterator<        \
  CRY_FOREACH_AUTO_ITERATOR_COUNT()                 \
>(EXPRESSION)



#define CRY_FOREACH(ITERATOR_NAME, RANGE)                     \
if(CRY_FOREACH_AUTO_RANGE(                                    \
     CRY_FOREACH_AUTO_RANGE_FOR_ ## ITERATOR_NAME, RANGE      \
   ));                                                        \
else if(CRY_FOREACH_INCREMENT_AUTO_RANGE_COUNT());            \
else if(CRY_FOREACH_AUTO_ITERATOR(                            \
          CRY_FOREACH_AUTO_ITERATOR_END_FOR_ ## ITERATOR_NAME \
        , cry_foreach_auto_range_end(                         \
            CRY_FOREACH_AUTO_RANGE_FOR_ ## ITERATOR_NAME      \
          )                                                   \
        ));                                                   \
else if(CRY_FOREACH_AUTO_ITERATOR(                            \
          ITERATOR_NAME                                       \
        , cry_foreach_auto_range_begin(                       \
            CRY_FOREACH_AUTO_RANGE_FOR_ ## ITERATOR_NAME      \
          )                                                   \
        ));                                                   \
else if(CRY_FOREACH_INCREMENT_AUTO_ITERATOR_COUNT());         \
else                                                          \
  for(;                                                       \
      !cry_foreach_auto_iterator_equal_to(                    \
        ITERATOR_NAME                                         \
      , CRY_FOREACH_AUTO_ITERATOR_END_FOR_ ## ITERATOR_NAME   \
      );                                                      \
      cry_foreach_auto_iterator_increment(ITERATOR_NAME)      \
    )



//////////////////// ここまでライブラリのコード ////////////////////
////////////////////  以下,クライアントコード  ////////////////////



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

#include <boost/shared_ptr.hpp>
#include <boost/iterator/indirect_iterator.hpp>

template<class Range>
std::pair<
  boost::indirect_iterator<
    typename boost::range_result_iterator<Range>::type
  >
, boost::indirect_iterator<
    typename boost::range_result_iterator<Range>::type
  >
>
indirected(Range &r)
{
  return std::make_pair(
      boost::make_indirect_iterator(boost::begin(r))
    , boost::make_indirect_iterator(boost::end(r))
    );
}

int main()
{
  using namespace std;

  int a[10] = {1,2,3,4,5,6,7,8,9,10};
  int b[10] = {2,3,5,7,11,13,17,19,23,29};

  vector<int> v(boost::begin(b), boost::end(b));
  deque<int> d(boost::begin(a), boost::end(a));
  list<int> l(boost::begin(b), boost::end(b));

  // 基本
  // 全要素の表示
  CRY_FOREACH(it, v){
    cout << deref(it) << endl;
  }

  cout << "----------------------------------------" << endl;

  // continue
  // 要素が偶数なら "even",それ以外は普通に表示
  CRY_FOREACH(it, d){
    if(deref(it) % 2 == 0){
      cout << "even" << endl;
      continue;
    }
    else{
      cout << deref(it) << endl;
    }
  }

  cout << "----------------------------------------" << endl;

  // break
  // 10 以上の要素を表示した時点で break
  CRY_FOREACH(it, l){
    cout << deref(it) << endl;
    if(deref(it) > 10){
      cout << "breaked" << endl;
      break;
    }
  }

  cout << "----------------------------------------" << endl;

  vector<boost::shared_ptr<int> > vp;
  // 配列 
  CRY_FOREACH(it, b){
    vp.push_back(boost::shared_ptr<int>(new int(deref(it))));
  }

  // indirected range アダプタによる vector<shared_ptr<int> > の2重参照外し
  // + range が一時オブジェクトな場合の確認
  // 要素が shared_ptr<int> の vector を2重参照外しで実際の要素を表示
  CRY_FOREACH(it, indirected(vp)){
    cout << deref(it) << endl;
  }

  cout << "----------------------------------------" << endl;

  // 多重ループ + break + continue
  CRY_FOREACH(it1, a){
    if(deref(it1) % 2 == 0){
      continue;
    }

    CRY_FOREACH(it2, b){
      if(deref(it2) % 2 == 0){
        cout << "even" << endl;
        continue;
      }
      cout << '(' << deref(it1) << ',' << deref(it2) << ')' << endl;
      if(deref(it2) > 10){
        cout << "inner loop breaked" << endl;
        break;
      }
    }

    if(deref(it1) > 5){
      cout << "outer loop breaked" << endl;
      break;
    }
  }

  cout << "----------------------------------------" << endl;

  // 代入
  CRY_FOREACH(it, l){
    deref(it) *= 2;
  }

  CRY_FOREACH(it, l){
    cout << deref(it) << endl;
  }

  cout << "----------------------------------------" << endl;

  // GCC では ICE が出る.調査中.
  //// if 文との相性
  //if(false)
  //  CRY_FOREACH(it, v){}
  //else{
  //  cout << "here" << endl;
  //}
}