Index: boost/foreach.hpp =================================================================== --- boost/foreach.hpp (revision 78680) +++ boost/foreach.hpp (working copy) @@ -30,8 +30,22 @@ #include #include +// Some compilers support rvalue references and auto type deduction. +// With these C++11 features, temporary collections can be bound to +// rvalue references and their lifetime is extended. No copy/move is needed. +#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_AUTO_DECLARATIONS) \ + && !(BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ <= 6) && !defined(BOOST_INTEL) && \ + !defined(BOOST_CLANG)) \ + && !BOOST_WORKAROUND(BOOST_MSVC, == 1600) +# define BOOST_FOREACH_USE_CXX11 +// gcc 4.4-4.6 have bugs in auto type deduction. We use workaround codes +// on these compilers. +#elif !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_AUTO_DECLARATIONS) \ + && (BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ <= 6) && !defined(BOOST_INTEL) && \ + !defined(BOOST_CLANG)) +# define BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND // Some compilers let us detect even const-qualified rvalues at compile-time -#if !defined(BOOST_NO_RVALUE_REFERENCES) \ +#elif !defined(BOOST_NO_RVALUE_REFERENCES) \ || BOOST_WORKAROUND(BOOST_MSVC, >= 1310) && !defined(_PREFAST_) \ || (BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ <= 5) && !defined(BOOST_INTEL) && \ !defined(BOOST_CLANG)) \ @@ -88,6 +102,11 @@ #include #include +#if defined(BOOST_FOREACH_USE_CXX11) || defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +# include +# include +#endif + #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION # include # include @@ -95,6 +114,7 @@ # include #endif +#if !defined(BOOST_FOREACH_USE_CXX11) && !defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) namespace boost { @@ -153,11 +173,11 @@ } // namespace boost // vc6/7 needs help ordering the following overloads -#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING -# define BOOST_FOREACH_TAG_DEFAULT ... -#else -# define BOOST_FOREACH_TAG_DEFAULT boost::foreach::tag -#endif +# ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# define BOOST_FOREACH_TAG_DEFAULT ... +# else +# define BOOST_FOREACH_TAG_DEFAULT boost::foreach::tag +# endif /////////////////////////////////////////////////////////////////////////////// // boost_foreach_is_lightweight_proxy @@ -192,6 +212,7 @@ template inline boost::foreach::is_noncopyable * boost_foreach_is_noncopyable(T *&, BOOST_FOREACH_TAG_DEFAULT) { return 0; } +#endif namespace boost { @@ -199,6 +220,7 @@ namespace foreach_detail_ { +#if !defined(BOOST_FOREACH_USE_CXX11) && !defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) /////////////////////////////////////////////////////////////////////////////// // Define some utilities for assessing the properties of expressions // @@ -223,22 +245,24 @@ template inline boost::is_const *is_const_(T &) { return 0; } -#ifndef BOOST_FOREACH_NO_RVALUE_DETECTION +# ifndef BOOST_FOREACH_NO_RVALUE_DETECTION template inline boost::mpl::true_ *is_const_(T const &) { return 0; } -#endif +# endif -#ifdef BOOST_NO_RVALUE_REFERENCES +# ifdef BOOST_NO_RVALUE_REFERENCES template inline boost::mpl::false_ *is_rvalue_(T &, int) { return 0; } template inline boost::mpl::true_ *is_rvalue_(T const &, ...) { return 0; } -#else +# else template inline boost::is_rvalue_reference *is_rvalue_(T &&, int) { return 0; } +# endif #endif +#if !defined(BOOST_FOREACH_USE_CXX11) /////////////////////////////////////////////////////////////////////////////// // auto_any_t/auto_any // General utility for putting an object of any type into automatic storage @@ -268,12 +292,30 @@ typedef auto_any_base const &auto_any_t; +# if defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +template +inline T &auto_any_cast(auto_any_t a) +{ + return static_cast const &>(a).item; +} +# else template inline BOOST_DEDUCED_TYPENAME boost::mpl::if_::type &auto_any_cast(auto_any_t a) { return static_cast const &>(a).item; } +# endif +# if defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +template +inline auto_any make_auto_any(T t) +{ + return auto_any(t); +} +# endif +#endif + +#if !defined(BOOST_FOREACH_USE_CXX11) && !defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) typedef boost::mpl::true_ const_; /////////////////////////////////////////////////////////////////////////////// @@ -284,6 +326,7 @@ : boost::mpl::if_ { }; +#endif template struct wrap_cstr @@ -334,7 +377,7 @@ > {}; -template +template struct foreach_iterator { // **** READ THIS IF YOUR COMPILE BREAKS HERE **** @@ -364,8 +407,16 @@ >::type type; }; +#if defined(BOOST_FOREACH_USE_CXX11) || defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +// just a shortcut for foreach_iterator<..., ...> +template +struct foreach_iterator_ + : foreach_iterator::type, boost::is_const > +{ +}; +#endif -template +template struct foreach_reverse_iterator { // **** READ THIS IF YOUR COMPILE BREAKS HERE **** @@ -395,12 +446,31 @@ >::type type; }; -template +#if defined(BOOST_FOREACH_USE_CXX11) || defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +// just a shortcut for foreach_reverse_iterator<..., ...> +template +struct foreach_reverse_iterator_ + : foreach_reverse_iterator::type, boost::is_const > +{ +}; +#endif + +template struct foreach_reference : iterator_reference::type> { }; +#if defined(BOOST_FOREACH_USE_CXX11) || defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +// just a shortcut for foreach_reference<..., ...> +template +struct foreach_reference_ + : foreach_reference::type, boost::is_const > +{ +}; +#endif + +#if !defined(BOOST_FOREACH_USE_CXX11) && !defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) /////////////////////////////////////////////////////////////////////////////// // encode_type // @@ -430,14 +500,14 @@ } // Borland needs a little extra help with arrays -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) template inline T (*&to_ptr(T (&)[N]))[N] { static T (*t)[N] = 0; return t; } -#endif +# endif /////////////////////////////////////////////////////////////////////////////// // derefof @@ -454,18 +524,18 @@ ); } -#if defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) \ - && !defined(BOOST_NO_RVALUE_REFERENCES) +# if defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) \ + && !defined(BOOST_NO_RVALUE_REFERENCES) /////////////////////////////////////////////////////////////////////////////// // Rvalue references makes it drop-dead simple to detect at compile time // whether an expression is an rvalue. /////////////////////////////////////////////////////////////////////////////// -# define BOOST_FOREACH_IS_RVALUE(COL) \ +# define BOOST_FOREACH_IS_RVALUE(COL) \ boost::foreach_detail_::is_rvalue_((COL), 0) -#elif defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) \ - && defined(BOOST_NO_RVALUE_REFERENCES) +# elif defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) \ + && defined(BOOST_NO_RVALUE_REFERENCES) /////////////////////////////////////////////////////////////////////////////// // Detect at compile-time whether an expression yields an rvalue or // an lvalue. This is rather non-standard, but some popular compilers @@ -493,13 +563,13 @@ return rvalue_probe(); } -# define BOOST_FOREACH_IS_RVALUE(COL) \ +# define BOOST_FOREACH_IS_RVALUE(COL) \ boost::foreach_detail_::and_( \ boost::foreach_detail_::not_(boost::foreach_detail_::is_array_(COL)) \ , (true ? 0 : boost::foreach_detail_::is_rvalue_( \ (true ? boost::foreach_detail_::make_probe(COL) : (COL)), 0))) -#elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION) +# elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION) /////////////////////////////////////////////////////////////////////////////// // Detect at run-time whether an expression yields an rvalue // or an lvalue. This is 100% standard C++, but not all compilers @@ -618,11 +688,13 @@ return is_rvalue; } +# endif #endif /////////////////////////////////////////////////////////////////////////////// // contain // +#if !defined(BOOST_FOREACH_USE_CXX11) && !defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) template inline auto_any contain(T const &t, boost::mpl::true_ *) // rvalue { @@ -640,18 +712,41 @@ #endif } -#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION +# ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION template inline auto_any > contain(T const &t, bool *rvalue) { return auto_any >(*rvalue ? simple_variant(t) : simple_variant(&t)); } +# endif #endif ///////////////////////////////////////////////////////////////////////////// // begin // +#if defined(BOOST_FOREACH_USE_CXX11) || defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +template +inline typename boost::disable_if< + boost::is_pointer + , typename foreach_iterator_::type +>::type +begin(T &col) +{ + return boost::begin(col); +} + +template +inline typename boost::enable_if< + boost::is_pointer + , typename foreach_iterator_::type +>::type +begin(T &col) // null-terminated C-style strings +{ + return col; +} + +#else template inline auto_any::type> begin(auto_any_t col, type2type *, boost::mpl::true_ *) // rvalue @@ -670,7 +765,7 @@ iterator(boost::begin(derefof(auto_any_cast(col))))); } -#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION +# ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION template inline auto_any::type> begin(auto_any_t col, type2type *, bool *) @@ -678,20 +773,43 @@ return auto_any::type>( boost::begin(*auto_any_cast, boost::mpl::false_>(col).get())); } -#endif +# endif -#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING template inline auto_any begin(auto_any_t col, type2type *, boost::mpl::true_ *) // null-terminated C-style strings { return auto_any(auto_any_cast(col)); } +# endif #endif /////////////////////////////////////////////////////////////////////////////// // end // +#if defined(BOOST_FOREACH_USE_CXX11) || defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +template +inline typename boost::disable_if< + boost::is_pointer + , typename foreach_iterator_::type +>::type +end(T &col) +{ + return boost::end(col); +} + +template +inline typename boost::enable_if< + boost::is_pointer + , typename foreach_iterator_::type +>::type +end(T &col) // null-terminated C-style strings +{ + return 0; +} + +#else template inline auto_any::type> end(auto_any_t col, type2type *, boost::mpl::true_ *) // rvalue @@ -710,7 +828,7 @@ iterator(boost::end(derefof(auto_any_cast(col))))); } -#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION +# ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION template inline auto_any::type> end(auto_any_t col, type2type *, bool *) @@ -718,20 +836,66 @@ return auto_any::type>( boost::end(*auto_any_cast, boost::mpl::false_>(col).get())); } -#endif +# endif -#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING template inline auto_any end(auto_any_t, type2type *, boost::mpl::true_ *) // null-terminated C-style strings { return auto_any(0); // not used } +# endif #endif /////////////////////////////////////////////////////////////////////////////// // done // +#if defined(BOOST_FOREACH_USE_CXX11) +template +inline typename boost::disable_if< + boost::is_pointer + , bool +>::type +done(Iterator const &cur, Iterator const &end, Col &) +{ + return cur == end; +} + +template +inline typename boost::enable_if< + boost::is_pointer + , bool +>::type +done(Iterator const &cur, Iterator const &end, Col &) // null-terminated C-style strings +{ + return *cur == 0; +} + +#elif defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +template +inline typename boost::disable_if< + boost::is_pointer + , bool +>::type +done(auto_any_t cur, auto_any_t end, Col &) +{ + typedef typename foreach_iterator_::type iterator; + return auto_any_cast(cur) == auto_any_cast(end); +} + +template +inline typename boost::enable_if< + boost::is_pointer + , bool +>::type +done(auto_any_t cur, auto_any_t, Col &) // null-terminated C-style strings +{ + typedef typename foreach_iterator_::type iterator; + return *auto_any_cast(cur) == 0; +} + +#else template inline bool done(auto_any_t cur, auto_any_t end, type2type *) { @@ -739,27 +903,63 @@ return auto_any_cast(cur) == auto_any_cast(end); } -#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING template inline bool done(auto_any_t cur, auto_any_t, type2type *) // null-terminated C-style strings { return ! *auto_any_cast(cur); } +# endif #endif /////////////////////////////////////////////////////////////////////////////// // next // +#if defined(BOOST_FOREACH_USE_CXX11) +template +inline void next(Iterator &cur, Col &) +{ + ++cur; +} + +#elif defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +template +inline void next(auto_any_t cur, Col &) +{ + typedef typename foreach_iterator_::type iterator; + ++auto_any_cast(cur); +} + +#else template inline void next(auto_any_t cur, type2type *) { typedef BOOST_DEDUCED_TYPENAME foreach_iterator::type iter_t; ++auto_any_cast(cur); } +#endif /////////////////////////////////////////////////////////////////////////////// // deref // +#if defined(BOOST_FOREACH_USE_CXX11) +template +inline typename foreach_reference_::type +deref(Iterator const &cur, Col &) +{ + return *cur; +} + +#elif defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +template +inline typename foreach_reference_::type +deref(auto_any_t cur, Col &) +{ + typedef typename foreach_iterator_::type iterator; + return *auto_any_cast(cur); +} + +#else template inline BOOST_DEDUCED_TYPENAME foreach_reference::type deref(auto_any_t cur, type2type *) @@ -767,10 +967,37 @@ typedef BOOST_DEDUCED_TYPENAME foreach_iterator::type iter_t; return *auto_any_cast(cur); } +#endif ///////////////////////////////////////////////////////////////////////////// // rbegin // +#if defined(BOOST_FOREACH_USE_CXX11) || defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +template +inline typename boost::disable_if< + boost::is_pointer + , typename foreach_reverse_iterator_::type +>::type +rbegin(T &col) +{ + return boost::rbegin(col); +} + +template +inline typename boost::enable_if< + boost::is_pointer + , typename foreach_reverse_iterator_::type +>::type +rbegin(T &col) // null-terminated C-style strings +{ + typedef typename remove_const::type pointer; + pointer p = col; + while(0 != *p) + ++p; + return typename foreach_reverse_iterator_::type(p); +} + +#else template inline auto_any::type> rbegin(auto_any_t col, type2type *, boost::mpl::true_ *) // rvalue @@ -789,7 +1016,7 @@ iterator(boost::rbegin(derefof(auto_any_cast(col))))); } -#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION +# ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION template inline auto_any::type> rbegin(auto_any_t col, type2type *, bool *) @@ -797,9 +1024,9 @@ return auto_any::type>( boost::rbegin(*auto_any_cast, boost::mpl::false_>(col).get())); } -#endif +# endif -#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING template inline auto_any > rbegin(auto_any_t col, type2type *, boost::mpl::true_ *) // null-terminated C-style strings @@ -809,11 +1036,34 @@ ++p; return auto_any >(reverse_iterator(p)); } +# endif #endif /////////////////////////////////////////////////////////////////////////////// // rend // +#if defined(BOOST_FOREACH_USE_CXX11) || defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +template +inline typename boost::disable_if< + boost::is_pointer + , typename foreach_reverse_iterator_::type +>::type +rend(T &col) +{ + return boost::rend(col); +} + +template +inline typename boost::enable_if< + boost::is_pointer + , typename foreach_reverse_iterator_::type +>::type +rend(T &col) // null-terminated C-style strings +{ + return typename foreach_reverse_iterator_::type(col); +} + +#else template inline auto_any::type> rend(auto_any_t col, type2type *, boost::mpl::true_ *) // rvalue @@ -832,7 +1082,7 @@ iterator(boost::rend(derefof(auto_any_cast(col))))); } -#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION +# ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION template inline auto_any::type> rend(auto_any_t col, type2type *, bool *) @@ -840,9 +1090,9 @@ return auto_any::type>( boost::rend(*auto_any_cast, boost::mpl::false_>(col).get())); } -#endif +# endif -#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING template inline auto_any > rend(auto_any_t col, type2type *, boost::mpl::true_ *) // null-terminated C-style strings @@ -850,31 +1100,84 @@ return auto_any >( reverse_iterator(auto_any_cast(col))); } +# endif #endif /////////////////////////////////////////////////////////////////////////////// // rdone // +#if defined(BOOST_FOREACH_USE_CXX11) +template +inline bool rdone(Iterator const &cur, Iterator const &end, Col &) +{ + return cur == end; +} + +#elif defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +template +inline bool rdone(auto_any_t cur, auto_any_t end, Col &) +{ + typedef typename foreach_reverse_iterator_::type iterator; + return auto_any_cast(cur) == auto_any_cast(end); +} + +#else template inline bool rdone(auto_any_t cur, auto_any_t end, type2type *) { typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator::type iter_t; return auto_any_cast(cur) == auto_any_cast(end); } +#endif /////////////////////////////////////////////////////////////////////////////// // rnext // +#if defined(BOOST_FOREACH_USE_CXX11) +template +inline void rnext(Iterator &cur, Col &) +{ + ++cur; +} + +#elif defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +template +inline void rnext(auto_any_t cur, Col &) +{ + typedef typename foreach_reverse_iterator_::type iterator; + ++auto_any_cast(cur); +} + +#else template inline void rnext(auto_any_t cur, type2type *) { typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator::type iter_t; ++auto_any_cast(cur); } +#endif /////////////////////////////////////////////////////////////////////////////// // rderef // +#if defined(BOOST_FOREACH_USE_CXX11) +template +inline typename foreach_reference_::type +rderef(Iterator const &cur, Col &) +{ + return *cur; +} + +#elif defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +template +inline typename foreach_reference_::type +rderef(auto_any_t cur, Col &) +{ + typedef typename foreach_reverse_iterator_::type iterator; + return *auto_any_cast(cur); +} + +#else template inline BOOST_DEDUCED_TYPENAME foreach_reference::type rderef(auto_any_t cur, type2type *) @@ -882,6 +1185,7 @@ typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator::type iter_t; return *auto_any_cast(cur); } +#endif } // namespace foreach_detail_ } // namespace boost @@ -904,26 +1208,93 @@ # define BOOST_FOREACH_ID(x) BOOST_PP_CAT(x, __LINE__) #endif +#if !defined(BOOST_FOREACH_USE_CXX11) && !defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) // A sneaky way to get the type of the collection without evaluating the expression -#define BOOST_FOREACH_TYPEOF(COL) \ +# define BOOST_FOREACH_TYPEOF(COL) \ (true ? 0 : boost::foreach_detail_::encode_type(COL, boost::foreach_detail_::is_const_(COL))) // returns true_* if the type is noncopyable -#define BOOST_FOREACH_IS_NONCOPYABLE(COL) \ +# define BOOST_FOREACH_IS_NONCOPYABLE(COL) \ boost_foreach_is_noncopyable( \ boost::foreach_detail_::to_ptr(COL) \ , boost_foreach_argument_dependent_lookup_hack_value) // returns true_* if the type is a lightweight proxy (and is not noncopyable) -#define BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL) \ +# define BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL) \ boost::foreach_detail_::and_( \ boost::foreach_detail_::not_(BOOST_FOREACH_IS_NONCOPYABLE(COL)) \ , boost_foreach_is_lightweight_proxy( \ boost::foreach_detail_::to_ptr(COL) \ , boost_foreach_argument_dependent_lookup_hack_value)) +#endif -#if defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) +#if defined(BOOST_FOREACH_USE_CXX11) /////////////////////////////////////////////////////////////////////////////// +// R-values and const R-values are bound to rvalue references +/////////////////////////////////////////////////////////////////////////////// + +// No variable is needed to track the rvalue-ness of the collection expression +# define BOOST_FOREACH_PREAMBLE() \ + BOOST_FOREACH_SUPPRESS_WARNINGS() + +namespace boost { namespace foreach_detail_ +{ + template + inline boost::is_rvalue_reference *is_rvalue(T &&) { return 0; } + + template + inline typename boost::mpl::if_::type + add_const_if(T &t, Cond *) + { + return t; + } +}} + +# define BOOST_FOREACH_IS_RVALUE(COL) (true ? 0 : boost::foreach_detail_::is_rvalue(COL)) + +// Non-const rvalue collections are accessed as const references. +# define BOOST_FOREACH_REF(COL) \ + boost::foreach_detail_::add_const_if( \ + BOOST_FOREACH_ID(_foreach_col) \ + , BOOST_FOREACH_IS_RVALUE(COL)) + +#elif defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +/////////////////////////////////////////////////////////////////////////////// +// R-values and const R-values are bound to const lvalue references +/////////////////////////////////////////////////////////////////////////////// + +// No variable is needed to track the rvalue-ness of the collection expression +# define BOOST_FOREACH_PREAMBLE() \ + BOOST_FOREACH_SUPPRESS_WARNINGS() + +namespace boost { namespace foreach_detail_ +{ + template + inline boost::mpl::true_ *is_nonconst_lvalue(T&) { return 0; } + + template + inline boost::mpl::false_ *is_nonconst_lvalue(T const&) { return 0; } + + template + inline typename boost::mpl::if_::type &, T &>::type + remove_const_if(T &t, Cond *) + { + return const_cast< + typename boost::mpl::if_::type &, T &>::type + >(t); + } +}} + +# define BOOST_FOREACH_IS_NONCONST_LVALUE(COL) (true ? 0 : boost::foreach_detail_::is_nonconst_lvalue(COL)) + +// Only non-const lvalue collections are accessed as non-const references. +# define BOOST_FOREACH_REF(COL) \ + boost::foreach_detail_::remove_const_if( \ + BOOST_FOREACH_ID(_foreach_col) \ + , BOOST_FOREACH_IS_NONCONST_LVALUE(COL)) + +#elif defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) +/////////////////////////////////////////////////////////////////////////////// // R-values and const R-values supported here with zero runtime overhead /////////////////////////////////////////////////////////////////////////////// @@ -1005,67 +1376,172 @@ #endif -#define BOOST_FOREACH_CONTAIN(COL) \ +#if defined(BOOST_FOREACH_USE_CXX11) +# define BOOST_FOREACH_BEGIN(COL) \ + boost::foreach_detail_::begin( \ + BOOST_FOREACH_REF(COL)) + +# define BOOST_FOREACH_END(COL) \ + boost::foreach_detail_::end( \ + BOOST_FOREACH_REF(COL)) + +# define BOOST_FOREACH_DONE(COL) \ + boost::foreach_detail_::done( \ + BOOST_FOREACH_ID(_foreach_cur) \ + , BOOST_FOREACH_ID(_foreach_end) \ + , BOOST_FOREACH_REF(COL)) + +# define BOOST_FOREACH_NEXT(COL) \ + boost::foreach_detail_::next( \ + BOOST_FOREACH_ID(_foreach_cur) \ + , BOOST_FOREACH_REF(COL)) + +# define BOOST_FOREACH_DEREF(COL) \ + boost::foreach_detail_::deref( \ + BOOST_FOREACH_ID(_foreach_cur) \ + , BOOST_FOREACH_REF(COL)) + +# define BOOST_FOREACH_RBEGIN(COL) \ + boost::foreach_detail_::rbegin( \ + BOOST_FOREACH_REF(COL)) + +# define BOOST_FOREACH_REND(COL) \ + boost::foreach_detail_::rend( \ + BOOST_FOREACH_REF(COL)) + +# define BOOST_FOREACH_RDONE(COL) \ + boost::foreach_detail_::rdone( \ + BOOST_FOREACH_ID(_foreach_cur) \ + , BOOST_FOREACH_ID(_foreach_end) \ + , BOOST_FOREACH_REF(COL)) + +# define BOOST_FOREACH_RNEXT(COL) \ + boost::foreach_detail_::rnext( \ + BOOST_FOREACH_ID(_foreach_cur) \ + , BOOST_FOREACH_REF(COL)) + +# define BOOST_FOREACH_RDEREF(COL) \ + boost::foreach_detail_::rderef( \ + BOOST_FOREACH_ID(_foreach_cur) \ + , BOOST_FOREACH_REF(COL)) + +#elif defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +# define BOOST_FOREACH_BEGIN(COL) \ + boost::foreach_detail_::make_auto_any( \ + boost::foreach_detail_::begin( \ + BOOST_FOREACH_REF(COL))) + +# define BOOST_FOREACH_END(COL) \ + boost::foreach_detail_::make_auto_any( \ + boost::foreach_detail_::end( \ + BOOST_FOREACH_REF(COL))) + +# define BOOST_FOREACH_DONE(COL) \ + boost::foreach_detail_::done( \ + BOOST_FOREACH_ID(_foreach_cur) \ + , BOOST_FOREACH_ID(_foreach_end) \ + , BOOST_FOREACH_REF(COL)) + +# define BOOST_FOREACH_NEXT(COL) \ + boost::foreach_detail_::next( \ + BOOST_FOREACH_ID(_foreach_cur) \ + , BOOST_FOREACH_REF(COL)) + +# define BOOST_FOREACH_DEREF(COL) \ + boost::foreach_detail_::deref( \ + BOOST_FOREACH_ID(_foreach_cur) \ + , BOOST_FOREACH_REF(COL)) + +# define BOOST_FOREACH_RBEGIN(COL) \ + boost::foreach_detail_::make_auto_any( \ + boost::foreach_detail_::rbegin( \ + BOOST_FOREACH_REF(COL))) + +# define BOOST_FOREACH_REND(COL) \ + boost::foreach_detail_::make_auto_any( \ + boost::foreach_detail_::rend( \ + BOOST_FOREACH_REF(COL))) + +# define BOOST_FOREACH_RDONE(COL) \ + boost::foreach_detail_::rdone( \ + BOOST_FOREACH_ID(_foreach_cur) \ + , BOOST_FOREACH_ID(_foreach_end) \ + , BOOST_FOREACH_REF(COL)) + +# define BOOST_FOREACH_RNEXT(COL) \ + boost::foreach_detail_::rnext( \ + BOOST_FOREACH_ID(_foreach_cur) \ + , BOOST_FOREACH_REF(COL)) + +# define BOOST_FOREACH_RDEREF(COL) \ + boost::foreach_detail_::rderef( \ + BOOST_FOREACH_ID(_foreach_cur) \ + , BOOST_FOREACH_REF(COL)) + +#else +# define BOOST_FOREACH_CONTAIN(COL) \ boost::foreach_detail_::contain( \ BOOST_FOREACH_EVALUATE(COL) \ , BOOST_FOREACH_SHOULD_COPY(COL)) -#define BOOST_FOREACH_BEGIN(COL) \ +# define BOOST_FOREACH_BEGIN(COL) \ boost::foreach_detail_::begin( \ BOOST_FOREACH_ID(_foreach_col) \ , BOOST_FOREACH_TYPEOF(COL) \ , BOOST_FOREACH_SHOULD_COPY(COL)) -#define BOOST_FOREACH_END(COL) \ +# define BOOST_FOREACH_END(COL) \ boost::foreach_detail_::end( \ BOOST_FOREACH_ID(_foreach_col) \ , BOOST_FOREACH_TYPEOF(COL) \ , BOOST_FOREACH_SHOULD_COPY(COL)) -#define BOOST_FOREACH_DONE(COL) \ +# define BOOST_FOREACH_DONE(COL) \ boost::foreach_detail_::done( \ BOOST_FOREACH_ID(_foreach_cur) \ , BOOST_FOREACH_ID(_foreach_end) \ , BOOST_FOREACH_TYPEOF(COL)) -#define BOOST_FOREACH_NEXT(COL) \ +# define BOOST_FOREACH_NEXT(COL) \ boost::foreach_detail_::next( \ BOOST_FOREACH_ID(_foreach_cur) \ , BOOST_FOREACH_TYPEOF(COL)) -#define BOOST_FOREACH_DEREF(COL) \ +# define BOOST_FOREACH_DEREF(COL) \ boost::foreach_detail_::deref( \ BOOST_FOREACH_ID(_foreach_cur) \ , BOOST_FOREACH_TYPEOF(COL)) -#define BOOST_FOREACH_RBEGIN(COL) \ +# define BOOST_FOREACH_RBEGIN(COL) \ boost::foreach_detail_::rbegin( \ BOOST_FOREACH_ID(_foreach_col) \ , BOOST_FOREACH_TYPEOF(COL) \ , BOOST_FOREACH_SHOULD_COPY(COL)) -#define BOOST_FOREACH_REND(COL) \ +# define BOOST_FOREACH_REND(COL) \ boost::foreach_detail_::rend( \ BOOST_FOREACH_ID(_foreach_col) \ , BOOST_FOREACH_TYPEOF(COL) \ , BOOST_FOREACH_SHOULD_COPY(COL)) -#define BOOST_FOREACH_RDONE(COL) \ +# define BOOST_FOREACH_RDONE(COL) \ boost::foreach_detail_::rdone( \ BOOST_FOREACH_ID(_foreach_cur) \ , BOOST_FOREACH_ID(_foreach_end) \ , BOOST_FOREACH_TYPEOF(COL)) -#define BOOST_FOREACH_RNEXT(COL) \ +# define BOOST_FOREACH_RNEXT(COL) \ boost::foreach_detail_::rnext( \ BOOST_FOREACH_ID(_foreach_cur) \ , BOOST_FOREACH_TYPEOF(COL)) -#define BOOST_FOREACH_RDEREF(COL) \ +# define BOOST_FOREACH_RDEREF(COL) \ boost::foreach_detail_::rderef( \ BOOST_FOREACH_ID(_foreach_cur) \ , BOOST_FOREACH_TYPEOF(COL)) +#endif + /////////////////////////////////////////////////////////////////////////////// // BOOST_FOREACH // @@ -1092,8 +1568,41 @@ // BOOST_FOREACH(i, int_list) // { ... } // -#define BOOST_FOREACH(VAR, COL) \ +#if defined(BOOST_FOREACH_USE_CXX11) +# define BOOST_FOREACH(VAR, COL) \ BOOST_FOREACH_PREAMBLE() \ + if (bool BOOST_FOREACH_ID(_foreach_col_defined) = false) {} else \ + for (auto &&BOOST_FOREACH_ID(_foreach_col) = (COL); \ + !BOOST_FOREACH_ID(_foreach_col_defined); BOOST_FOREACH_ID(_foreach_col_defined) = true) \ + if (bool BOOST_FOREACH_ID(_foreach_cur_defined) = false) {} else \ + for (auto BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_BEGIN(COL); \ + !BOOST_FOREACH_ID(_foreach_cur_defined); BOOST_FOREACH_ID(_foreach_cur_defined) = true) \ + if (bool BOOST_FOREACH_ID(_foreach_end_defined) = false) {} else \ + for (auto BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_END(COL); \ + !BOOST_FOREACH_ID(_foreach_end_defined); BOOST_FOREACH_ID(_foreach_end_defined) = true) \ + for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \ + BOOST_FOREACH_ID(_foreach_continue) && !BOOST_FOREACH_DONE(COL); \ + BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_NEXT(COL) : (void)0) \ + if ( (BOOST_FOREACH_ID(_foreach_continue) = false) ) {} else \ + for (VAR = BOOST_FOREACH_DEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true) + +#elif defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +# define BOOST_FOREACH(VAR, COL) \ + BOOST_FOREACH_PREAMBLE() \ + if (bool BOOST_FOREACH_ID(_foreach_col_defined) = false) {} else \ + for (auto const &BOOST_FOREACH_ID(_foreach_col) = (COL); \ + !BOOST_FOREACH_ID(_foreach_col_defined); BOOST_FOREACH_ID(_foreach_col_defined) = true) \ + if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_BEGIN(COL)) {} else \ + if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_END(COL)) {} else \ + for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \ + BOOST_FOREACH_ID(_foreach_continue) && !BOOST_FOREACH_DONE(COL); \ + BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_NEXT(COL) : (void)0) \ + if ( (BOOST_FOREACH_ID(_foreach_continue) = false) ) {} else \ + for (VAR = BOOST_FOREACH_DEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true) + +#else +# define BOOST_FOREACH(VAR, COL) \ + BOOST_FOREACH_PREAMBLE() \ if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL)) {} else \ if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_BEGIN(COL)) {} else \ if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_END(COL)) {} else \ @@ -1103,6 +1612,8 @@ if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) {} else \ for (VAR = BOOST_FOREACH_DEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true) +#endif + /////////////////////////////////////////////////////////////////////////////// // BOOST_REVERSE_FOREACH // @@ -1110,8 +1621,44 @@ // all other respects, BOOST_REVERSE_FOREACH is like // BOOST_FOREACH. // -#define BOOST_REVERSE_FOREACH(VAR, COL) \ +#if defined(BOOST_FOREACH_USE_CXX11) +# define BOOST_REVERSE_FOREACH(VAR, COL) \ BOOST_FOREACH_PREAMBLE() \ + if (bool BOOST_FOREACH_ID(_foreach_col_defined) = false) {} else \ + for (auto &&BOOST_FOREACH_ID(_foreach_col) = (COL); \ + !BOOST_FOREACH_ID(_foreach_col_defined); BOOST_FOREACH_ID(_foreach_col_defined) = true) \ + \ + if (bool BOOST_FOREACH_ID(_foreach_cur_defined) = false) {} else \ + for (auto BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_RBEGIN(COL); \ + !BOOST_FOREACH_ID(_foreach_cur_defined); BOOST_FOREACH_ID(_foreach_cur_defined) = true) \ + \ + if (bool BOOST_FOREACH_ID(_foreach_end_defined) = false) {} else \ + for (auto BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_REND(COL); \ + !BOOST_FOREACH_ID(_foreach_end_defined); BOOST_FOREACH_ID(_foreach_end_defined) = true) \ + \ + for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \ + BOOST_FOREACH_ID(_foreach_continue) && !BOOST_FOREACH_RDONE(COL); \ + BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_RNEXT(COL) : (void)0) \ + if ( (BOOST_FOREACH_ID(_foreach_continue) = false) ) {} else \ + for (VAR = BOOST_FOREACH_RDEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true) + +#elif defined(BOOST_FOREACH_USE_CXX11_GCC_WORKAROUND) +# define BOOST_REVERSE_FOREACH(VAR, COL) \ + BOOST_FOREACH_PREAMBLE() \ + if (bool BOOST_FOREACH_ID(_foreach_col_defined) = false) {} else \ + for (auto const &BOOST_FOREACH_ID(_foreach_col) = (COL); \ + !BOOST_FOREACH_ID(_foreach_col_defined); BOOST_FOREACH_ID(_foreach_col_defined) = true) \ + if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_RBEGIN(COL)) {} else \ + if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_REND(COL)) {} else \ + for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \ + BOOST_FOREACH_ID(_foreach_continue) && !BOOST_FOREACH_RDONE(COL); \ + BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_RNEXT(COL) : (void)0) \ + if ( (BOOST_FOREACH_ID(_foreach_continue) = false) ) {} else \ + for (VAR = BOOST_FOREACH_RDEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true) + +#else +# define BOOST_REVERSE_FOREACH(VAR, COL) \ + BOOST_FOREACH_PREAMBLE() \ if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL)) {} else \ if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_RBEGIN(COL)) {} else \ if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_REND(COL)) {} else \ @@ -1122,3 +1669,5 @@ for (VAR = BOOST_FOREACH_RDEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true) #endif + +#endif