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; //} }