2012-12-12 4 views
0

부스트가 필요없는 BOOST_FOREACH과 같은 "for each"매크로가 구현되어 있습니까?부스트가없는 BOOST_FOREACH?

+2

내가 부스트에 익숙하지 않은 해요,하지만 C++ 11에서 어쩌면 표준 : : for_each를 가치를 확인하고 있습니다? 또한, C++ 11에서는 (int x : vec) {...}를 쓸 수 있습니다. – Spook

답변

3

나는 그것을 만들었습니다.
GCC와 MSVC에서 C++ 11 r-value 참조와 함께 작동해야하지만 오류가있는 경우 잘 테스트 해 보았습니다.
편집 : 문자열에 대한 지원이 추가되었습니다.

#include <iterator> 
#include <utility> 

#define foreach(v, r) \ 
    if (fe_detail::any const &fe_r_ = \ 
     fe_detail::make_range(r)) { } else \ 
    if (fe_detail::any const &fe_b_ = \ 
     fe_detail::begin(fe_r_, ((void)0, 1) ? NULL : fe_detail::twrap(r))) { } else \ 
    if (fe_detail::equal(\ 
     fe_b_, \ 
     fe_detail::end(fe_r_, ((void)0, 1) ? NULL : fe_detail::twrap(r)), \ 
     ((void)0, 1) ? NULL : fe_detail::twrap(r))) { } else \ 
    for (bool fe_c_ = false; \ 
     !fe_c_ && !fe_detail::equal(\ 
      fe_b_, \ 
      fe_detail::end(fe_r_, ((void)0, 1) ? NULL : fe_detail::twrap(r)), \ 
      ((void)0, 1) ? NULL : fe_detail::twrap(r)); \ 
     fe_detail::advance(fe_b_, 1, ((void)0, 1) ? NULL : fe_detail::twrap(r))) \ 
    for (v = (fe_detail::move(*fe_detail::iter(fe_b_, ((void)0, 1) ? NULL : fe_detail::twrap(r)))); \ 
     fe_c_ = !fe_c_;) 

namespace fe_detail 
{ 
    // Container traits 
    template<class C, class It> struct CT 
    { 
     typedef It It; 
     static It begin(C &c) { return c.begin(); } 
     static It end(C &c) { return c.end(); } 
    }; 

    // Range traits 
    template<class R> struct RT : public CT<R, typename R::iterator> { }; 
    template<class R> struct RT<R const> : public CT<R const, typename R::const_iterator> { }; 
    template<class R> struct RT<R &> : public RT<R> { }; 

    template<class T, bool B = T::value> struct enable_if; 
    template<class T> struct enable_if<T, true> { typedef T type; }; 

    template<class T> struct is_char { static bool const value = false; }; 
    template<class T> struct is_char<T const> : public is_char<T> { }; 
    template<class T> struct is_char<T volatile> : public is_char<T> { }; 
    template<> struct is_char<char> { static bool const value = true; }; 
    template<> struct is_char<wchar_t> { static bool const value = true; }; 

    template<class Ch> struct RT<Ch *> : enable_if<is_char<Ch> > 
    { 
     typedef Ch *It; 
     static It begin(It a) { return &a[0]; } 
     static It end(It a) { return &a[std::char_traits<Ch>::length(a)]; } 
    }; 

    template<class R, size_t N> struct RT<R[N]> 
    { 
     typedef R *It; 
     static It begin(It a) { return &a[0]; } 
     static It end(It a) { return &a[N - (((void)0, is_char<R>::value) ? 1 : 0)]; } 
    }; 

    template<class It> struct RT<std::pair<It, It> > 
    { 
     typedef It It; 
     static It begin(std::pair<It, It> const a) { return a.first; } 
     static It end(std::pair<It, It> const a) { return a.second; } 
    }; 

    struct any { operator bool() const { return false; } }; 

    template<class T> struct type_wrap { type_wrap(bool = false) { } }; 

    template<class T> class wrap : public any 
    { wrap &operator =(wrap const &); public: mutable T v; wrap(T v) : any(), v(v) { } }; 

    template<class T> class wrap<T const> : public any 
    { wrap &operator =(wrap const &); public: T const v; wrap(T const v) : any(), v(v) { } }; 

    template<class T, size_t N> class wrap<T[N]> : public any 
    { wrap &operator =(wrap const &); public: T (&v)[N]; wrap(T (&v)[N]) : any(), v(v) { } }; 

    template<class T> class wrap<T const &> : public wrap<T const> 
    { wrap &operator =(wrap const &); public: wrap(T const &v) : wrap<T const>(v) { } }; 

    template<class T, size_t N> wrap<T[N]> make_range(T (&r)[N]) { return r; } 
    template<class T, size_t N> type_wrap<T[N]> twrap(T (&r)[N]) { throw 0; } 
    template<class It> type_wrap<std::pair<It, It> > twrap(std::pair<It, It> const &p) { throw 0; } 

#if defined(_MSC_VER) && _MSC_VER >= 1600 || defined(__RVALUE_REFERENCE) || defined(__GXX_EXPERIMENTAL_CXX0X__) 
    template<class R> struct RT<R &&> : public RT<R> { }; 
    template<class T> class wrap<T &&> : public wrap<T> { public: wrap(T &&v) : wrap<T>(std::move(v)) { } }; 

    template<class R> wrap<R &&> make_range(R &&r) { return wrap<R &&>(std::forward<R>(r)); } 
    template<class R> type_wrap<R> twrap(R &&) { throw 0; } 
    using std::move; 
#else 
    template<class R> wrap<R> make_range(R &r) { return r; } 
    template<class R> wrap<R const &> make_range(R const &r) { return r; } 

    template<class R> type_wrap<R> twrap(R &) { throw 0; } 
    template<class R> type_wrap<R const &> twrap(R const &) { throw 0; } 
    template<class T> T &move(T &v) { return v; } 
    template<class T> T const &move(T const &v) { return v; } 
#endif 

    template<class R> wrap<typename RT<R>::It> begin(any const &r, type_wrap<R>) 
    { return RT<R>::begin(static_cast<wrap<R> const &>(r).v); } 

    template<class R> wrap<typename RT<R>::It> end(any const &r, type_wrap<R>) 
    { return RT<R>::end (static_cast<wrap<R> const &>(r).v); } 

    template<class R> bool equal(any const &i, any const &j, type_wrap<R>) 
    { return static_cast<wrap<typename RT<R>::It> const &>(i).v == static_cast<wrap<typename RT<R>::It> const &>(j).v; } 

    template<class R> void advance(any const &i, typename std::iterator_traits<typename RT<R>::It>::difference_type const d, type_wrap<R>) 
    { return std::advance(static_cast<wrap<typename RT<R>::It> const &>(i).v, d); } 

    template<class R> typename RT<R>::It &iter(any const &i, type_wrap<R>) 
    { return static_cast<wrap<typename RT<R>::It> const &>(i).v; } 
} 

당신은 그것을 좋아 사용할 수 있습니다

#include <vector> 
#include <iostream> 

std::vector<int> make_vect() 
{ 
    std::vector<int> v; 
    v.push_back(5); 
    v.push_back(8); 
    v.push_back(10); 
    return v; 
} 

int main() 
{ 
    foreach (int c, make_vect()) 
    { 
     std::cout << c << std::endl; 
    } 
} 
+0

C++ 11을 사용할 수 있다면 매크로를 작성하는 요점은 무엇입니까? –

+0

@MatthieuM .: 코드를 보면 C++ 11이 작동하지 않아도된다는 것을 분명히 알 수 있습니다. – Mehrdad

+0

나는 당신의 메모에 코멘트를했다. GCC와 MSVC에서 C++ 11 r- 값 참조로도 작동해야한다. * –