BOOST_FOREACHを作ってみました
正式リリース前のBOOST_FOREACHのzip内にあるpptに作り方書いてるんですね
namespace shand { namespace foreach_detail { struct static_any_base { operator bool() const { return false; } }; template <class Type> struct static_any : static_any_base { static_any(const Type& item) : item_(item) {} mutable Type item_; }; typedef const static_any_base& static_any_t; template <class Type> inline Type& static_any_cast(static_any_t value) { return static_cast<const static_any<Type>&>(value).item_; } // array template <class Type, int Size> inline static_any<Type*> begin(Type (&ar)[Size], void*) { return ar; } template <class Type, int Size> inline static_any<Type*> end(Type (&ar)[Size], void*) { return ar + Size; } template <class Type, int Size> inline void next(static_any_t cur, Type (&)[Size], void*) { ++static_any_cast<Type*>(cur); } template <class Type, int Size> inline Type& extract(static_any_t cur, Type (&)[Size], void*) { return *static_any_cast<Type*>(cur); } template <class Type, int Size> inline bool done(static_any_t cur, static_any_t end, Type (&)[Size], void*) { return static_any_cast<Type*>(cur) == static_any_cast<Type*>(end); } // STL Container struct sfinae_types { typedef char yes; typedef struct { char arr[2]; } no; }; template <class Type> struct is_stl : sfinae_types { private: template <class Type> static yes check(typename Type::iterator*); template<class> static no check(...); public: enum { value = sizeof(yes)==sizeof(check<Type>(0)) }; }; // enable_if template <bool, class Type = void> struct enable_if_c { typedef Type type; }; template <class Type> struct enable_if_c<false, Type> {}; template <class Cond, class Type = void> struct enable_if : public enable_if_c<Cond::value, Type> {}; template <class Type> inline static_any<typename Type::iterator> begin(Type& container, typename enable_if<is_stl<Type> >::type*) { return container.begin(); } template <class Type> inline static_any<typename Type::iterator> end(Type& container, typename enable_if<is_stl<Type> >::type*) { return container.end(); } template <class Type> inline void next(static_any_t cur, Type&, typename enable_if<is_stl<Type> >::type*) { ++static_any_cast<typename Type::iterator>(cur); } template <class Type> inline typename Type::reference extract(static_any_t cur, Type&, typename enable_if<is_stl<Type> >::type*) { return *static_any_cast<typename Type::iterator>(cur); } template <class Type> inline bool done(static_any_t cur, static_any_t end, Type&, typename enable_if<is_stl<Type> >::type*) { typedef typename Type::iterator Iter; return static_any_cast<Iter>(cur) == static_any_cast<Iter>(end); } // foreach macro #define SHAND_FOREACH(VAR, COL) \ if (shand::foreach_detail::static_any_t _cur = shand::foreach_detail::begin(COL, 0) ) {} \ else if (shand::foreach_detail::static_any_t _end = shand::foreach_detail::end(COL, 0) ) {} \ else for (bool _continue = true; \ _continue && !shand::foreach_detail::done(_cur, _end, COL, 0); \ _continue ? shand::foreach_detail::next(_cur, COL, 0) : (void)&COL) \ if ((_continue = false) == true) {} \ else for (VAR = shand::foreach_detail::extract(_cur, COL, 0); !_continue; _continue = true) #define foreach SHAND_FOREACH }} // namespace shand::foreach_detail
配列
#include <iostream> #include <shand/foreach.hpp> using namespace std; int main() { int ar[3] = {3, 1, 4}; foreach (int value, ar) { cout << value << endl; } return 0; }
コンテナ(iterator型とreference型とbegin(), end()持ってればいい)
#include <iostream> #include <vector> #include <shand/foreach.hpp> using namespace std; int main() { vector<int> v; v.push_back(3); v.push_back(1); v.push_back(4); foreach (int value, v) { cout << value << endl; } return 0; }
参照も可能
foreach (int& value, v) {
++value;
}
break/continueも可能
foreach (int value, v) { break; }
※これが気に入らない人は消してください
#define foreach SHAND_FOREACH
※組み込み型以外のループには(const)参照を使いましょう
for文よりちょっと遅い程度で済みます
foreach (const Widget& widget, v)
...