#include #include #include #if !defined(FOREACH_MAX_COUNT) #define FOREACH_MAX_COUNT 100 #endif #define FOREACH_AUTO_RANGE_MAX_COUNT FOREACH_MAX_COUNT #define FOREACH_AUTO_ITERATOR_MAX_COUNT FOREACH_MAX_COUNT namespace foreach_detail{ template struct auto_range_count_tag : public auto_range_count_tag {}; template<> struct auto_range_count_tag<1> {}; struct auto_range_end_of_count_tag : public auto_range_count_tag< FOREACH_AUTO_RANGE_MAX_COUNT > {}; char (&test_auto_range_count(auto_range_count_tag<1>))[1]; template struct test_auto_range_count_injector { friend char (&test_auto_range_count(auto_range_count_tag))[n]; }; #define FOREACH_AUTO_RANGE_COUNT() \ sizeof( \ ::foreach_detail::test_auto_range_count( \ ::foreach_detail::auto_range_end_of_count_tag() \ ) \ ) #define FOREACH_INCREMENT_AUTO_RANGE_COUNT() \ sizeof( \ ::foreach_detail::test_auto_range_count_injector< \ FOREACH_AUTO_RANGE_COUNT() + 1 \ > \ ), 0 template struct auto_iterator_count_tag : public auto_iterator_count_tag {}; template<> struct auto_iterator_count_tag<1> {}; struct auto_iterator_end_of_count_tag : public auto_iterator_count_tag< FOREACH_AUTO_ITERATOR_MAX_COUNT > {}; char (&test_auto_iterator_count(auto_iterator_count_tag<1>))[1]; template struct test_auto_iterator_count_injector { friend char (&test_auto_iterator_count(auto_iterator_count_tag))[n]; }; #define FOREACH_AUTO_ITERATOR_COUNT() \ sizeof( \ ::foreach_detail::test_auto_iterator_count( \ ::foreach_detail::auto_iterator_end_of_count_tag() \ ) \ ) #define FOREACH_INCREMENT_AUTO_ITERATOR_COUNT() \ sizeof( \ ::foreach_detail::test_auto_iterator_count_injector< \ FOREACH_AUTO_ITERATOR_COUNT() + 1 \ > \ ), 0 template struct auto_range_base { operator bool() const { return false; } }; template class auto_range : public auto_range_base { public: auto_range(Iterator const &first, Iterator const &last) : first_(first) , last_(last) {} friend Iterator foreach_auto_range_begin( auto_range_base const &r ) { return static_cast(r).first_; } friend Iterator foreach_auto_range_end( auto_range_base const &r ) { return static_cast(r).last_; } private: Iterator first_; Iterator last_; }; // class auto_range template auto_range make_auto_range_impl(Iterator const &first, Iterator const &last) { return auto_range(first, last); } template auto_range::type> make_auto_range(Range &r) { return make_auto_range_impl(boost::begin(r), boost::end(r)); } template auto_range::type> make_auto_range(Range const &r) { return make_auto_range_impl(boost::begin(r), boost::end(r)); } template struct auto_iterator_base { operator bool() const { return false; } }; template class auto_iterator : public auto_iterator_base { public: typedef typename boost::iterator_reference::type reference; auto_iterator(Iterator const &iter) : iter_(iter) {} friend reference operator*( auto_iterator_base const &iter ) { return *static_cast(iter).iter_; } friend bool operator==( auto_iterator_base const &lhs , auto_iterator_base const &rhs ) { return static_cast(lhs).iter_ == static_cast(rhs).iter_; } friend bool operator==( auto_iterator_base const &lhs , Iterator const &rhs ) { return static_cast(lhs).iter_ == rhs; } friend bool operator==( Iterator const &lhs , auto_iterator_base const &rhs ) { return lhs == static_cast(rhs).iter_; } friend bool operator!=( auto_iterator_base const &lhs , auto_iterator_base const &rhs ) { return static_cast(lhs).iter_ != static_cast(rhs).iter_; } friend bool operator!=( auto_iterator_base const &lhs , Iterator const &rhs ) { return static_cast(lhs).iter_ != rhs; } friend bool operator!=( Iterator const &lhs , auto_iterator_base const &rhs ) { return lhs != static_cast(rhs).iter_; } friend Iterator &operator++( auto_iterator_base const &iter ) { return ++static_cast(iter).iter_; } private: mutable Iterator iter_; }; // class auto_iterator template auto_iterator make_auto_iterator(Iterator const &x) { return auto_iterator(x); } } // namespace foreach_detail #define FOREACH_AUTO_RANGE(NAME, EXPRESSION) \ ::foreach_detail::auto_range_base< \ FOREACH_AUTO_RANGE_COUNT() \ > const &NAME \ = ::foreach_detail::make_auto_range< \ FOREACH_AUTO_RANGE_COUNT() \ >(EXPRESSION) #define FOREACH_AUTO_ITERATOR(NAME, EXPRESSION) \ ::foreach_detail::auto_iterator_base< \ FOREACH_AUTO_ITERATOR_COUNT() \ > const &NAME \ = ::foreach_detail::make_auto_iterator< \ FOREACH_AUTO_ITERATOR_COUNT() \ >(EXPRESSION) #define FOREACH(ITERATOR_NAME, RANGE) \ if(FOREACH_AUTO_RANGE( \ FOREACH_AUTO_RANGE_FOR_ ## ITERATOR_NAME, RANGE \ )); \ else if(FOREACH_INCREMENT_AUTO_RANGE_COUNT()); \ else if(false) using foreach_detail::foreach_auto_range_begin; \ else if(false) using foreach_detail::foreach_auto_range_end; \ else if(FOREACH_AUTO_ITERATOR( \ FOREACH_AUTO_ITERATOR_END_FOR_ ## ITERATOR_NAME \ , foreach_auto_range_end( \ FOREACH_AUTO_RANGE_FOR_ ## ITERATOR_NAME \ ) \ )); \ else if(FOREACH_AUTO_ITERATOR( \ ITERATOR_NAME \ , foreach_auto_range_begin( \ FOREACH_AUTO_RANGE_FOR_ ## ITERATOR_NAME \ ) \ )); \ else if(FOREACH_INCREMENT_AUTO_ITERATOR_COUNT()); \ else if(false) using foreach_detail::operator==; \ else if(false) using foreach_detail::operator!=; \ else if(false) using foreach_detail::operator*; \ else if(false) using foreach_detail::operator++; \ else \ for(; \ ITERATOR_NAME != FOREACH_AUTO_ITERATOR_END_FOR_ ## ITERATOR_NAME; \ ++ ITERATOR_NAME \ ) //////////////////// the end of the library code //////////////////// //////////////////// the begininng of the client code //////////////////// #include #include #include #include #include #include #include #include template std::pair< boost::indirect_iterator< typename boost::range_result_iterator::type > , boost::indirect_iterator< typename boost::range_result_iterator::type > > indirected(Range &r) { std::cout << "Calling `indirected'." << std::endl; 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 v(boost::begin(a), boost::end(a)); deque d(boost::begin(b), boost::end(b)); { int *p = a; FOREACH(it, v){ assert(*it == *p); ++p; } } //////////////////////////////////////////////////////////// // continue FOREACH(it, v){ if(*it % 2 == 0){ *it = 0; continue; } *it = 1; } { int i = 1; FOREACH(it, v){ if(i % 2 == 0){ assert(*it == 0); } else{ assert(*it == 1); } ++i; } } v.assign(boost::begin(a), boost::end(a)); //////////////////////////////////////////////////////////// // break FOREACH(it, d){ *it = 0; if(*it > 10){ break; } } { deque::iterator it4 = d.begin() + 4; FOREACH(it, d){ assert(*it == 0); if(it == it4){ break; } } } d.assign(boost::begin(b), boost::end(b)); //////////////////////////////////////////////////////////// vector > vp; FOREACH(it, b){ vp.push_back(boost::shared_ptr(new int(*it))); } // with a range adaptor { int *p = b; FOREACH(it, indirected(vp)){ assert(*it == *p); ++p; } } //////////////////////////////////////////////////////////// // nested loop + break + continue { int sum = 0; FOREACH(it1, a){ FOREACH(it2, b){ if(*it2 % 2 == 0){ continue; } sum += *it1 * *it2; if(*it2 > 10){ break; } } } assert(sum == 1430); } //////////////////////////////////////////////////////////// // substitution FOREACH(it, d){ *it *= 2; } { int *p = b; FOREACH(it, d){ assert(*it == *p * 2); ++p; } } //////////////////////////////////////////////////////////// // interoperability vector::iterator iter5 = v.begin() + 5; { int i = 0; FOREACH(it, v){ if(iter5 == it){ assert(i == 5); } if(iter5 != it){ assert(i != 5); } if(it == iter5){ assert(i == 5); } if(it != iter5){ assert(i != 5); } ++i; } } }