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