Index: Boosty/boost-trunk/boost/foreach.hpp =================================================================== --- Boosty/boost-trunk/boost/foreach.hpp (revision 70472) +++ Boosty/boost-trunk/boost/foreach.hpp (working copy) @@ -30,8 +30,13 @@ #include #include +// Some compilers support rvalue references and auto type deduction. +// With these C++0x features, temporary collections can be bound to +// rvalue references and their lifetime is extended. No copy/move is needed. +#if !defined(BOOST_NO_DECLTYPE) && !defined(BOOST_NO_RVALUE_REFERENCES) +# define BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING // 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,11 +93,16 @@ #include #include +#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING +# include +# include +# include +#endif + #ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION # include # include # include -# include #endif namespace boost @@ -689,6 +699,29 @@ } #endif +#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING +template +inline typename foreach_iterator::type, is_const >::type +begin(T &col) +{ + return boost::begin(col); +} + +template +inline T * +begin(T *&col) +{ + return col; +} + +template +inline T * +begin(T * const &col) +{ + return col; +} +#endif + /////////////////////////////////////////////////////////////////////////////// // end // @@ -729,6 +762,33 @@ } #endif +#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING +template +inline typename foreach_iterator::type, is_const >::type +end(T &col) +{ + return boost::end(col); +} + +struct cstr_end_iterator +{ +}; + +template +inline cstr_end_iterator +end(T *&col) +{ + return cstr_end_iterator(); +} + +template +inline cstr_end_iterator +end(T * const &col) +{ + return cstr_end_iterator(); +} +#endif + /////////////////////////////////////////////////////////////////////////////// // done // @@ -747,6 +807,15 @@ } #endif +#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING +template +inline bool operator !=(Iterator cur, cstr_end_iterator) +{ + return *cur != 0; +} +#endif + + /////////////////////////////////////////////////////////////////////////////// // next // @@ -811,6 +880,35 @@ } #endif +#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING +template +inline typename foreach_reverse_iterator::type, is_const >::type +rbegin(T &col) +{ + return boost::rbegin(col); +} + +template +inline reverse_iterator +rbegin(T *&col) +{ + T *p = col; + while(0 != *p) + ++p; + return reverse_iterator(p); +} + +template +inline reverse_iterator +rbegin(T * const &col) +{ + T *p = col; + while(0 != *p) + ++p; + return reverse_iterator(p); +} +#endif + /////////////////////////////////////////////////////////////////////////////// // rend // @@ -852,6 +950,29 @@ } #endif +#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING +template +inline typename foreach_reverse_iterator::type, is_const >::type +rend(T &col) +{ + return boost::rend(col); +} + +template +inline reverse_iterator +rend(T *&col) +{ + return reverse_iterator(col); +} + +template +inline reverse_iterator +rend(T * const &col) +{ + return reverse_iterator(col); +} +#endif + /////////////////////////////////////////////////////////////////////////////// // rdone // @@ -922,11 +1043,41 @@ boost::foreach_detail_::to_ptr(COL) \ , boost_foreach_argument_dependent_lookup_hack_value)) -#if defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) /////////////////////////////////////////////////////////////////////////////// +// R-values and const R-values are bound to rvalue references +/////////////////////////////////////////////////////////////////////////////// +#if defined(BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING) +# define BOOST_FOREACH_PREAMBLE() \ + BOOST_FOREACH_SUPPRESS_WARNINGS() + +namespace boost { namespace foreach_detail_ +{ + template + typename remove_cv::type>::type decay_copy(T &&); + + template + T const add_const_if_rvalue(T &&); +}} +# define BOOST_FOREACH_AUTO_OBJECT(NAME, EXPR) \ + if (bool BOOST_PP_CAT(NAME, _defined) = false) {} else \ + for (decltype(boost::foreach_detail_::decay_copy(EXPR)) NAME = (EXPR); \ + !BOOST_PP_CAT(NAME, _defined); BOOST_PP_CAT(NAME, _defined) = true) + +// If EXPR is an rvalue, bind it to a const rvalue reference. +# define BOOST_FOREACH_AUTO_REF_REF(NAME, EXPR) \ + if (bool BOOST_PP_CAT(NAME, _defined) = false) {} else \ + for (decltype(boost::foreach_detail_::add_const_if_rvalue(EXPR)) &&NAME = (EXPR); \ + !BOOST_PP_CAT(NAME, _defined); BOOST_PP_CAT(NAME, _defined) = true) + +#elif defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION) +/////////////////////////////////////////////////////////////////////////////// // R-values and const R-values supported here with zero runtime overhead /////////////////////////////////////////////////////////////////////////////// +# define BOOST_FOREACH_PREAMBLE() \ + BOOST_FOREACH_SUPPRESS_WARNINGS() + + // No variable is needed to track the rvalue-ness of the collection expression # define BOOST_FOREACH_PREAMBLE() \ BOOST_FOREACH_SUPPRESS_WARNINGS() @@ -1092,7 +1243,28 @@ // BOOST_FOREACH(i, int_list) // { ... } // -#define BOOST_FOREACH(VAR, COL) \ +#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING +# define BOOST_FOREACH(VAR, COL) \ + BOOST_FOREACH_PREAMBLE() \ + BOOST_FOREACH_AUTO_REF_REF( \ + BOOST_FOREACH_ID(_foreach_col) \ + , COL) \ + BOOST_FOREACH_AUTO_OBJECT( \ + BOOST_FOREACH_ID(_foreach_cur) \ + , boost::foreach_detail_::begin(BOOST_FOREACH_ID(_foreach_col))) \ + BOOST_FOREACH_AUTO_OBJECT( \ + BOOST_FOREACH_ID(_foreach_end) \ + , boost::foreach_detail_::end(BOOST_FOREACH_ID(_foreach_col))) \ + for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \ + BOOST_FOREACH_ID(_foreach_continue) \ + && BOOST_FOREACH_ID(_foreach_cur) != BOOST_FOREACH_ID(_foreach_end); \ + BOOST_FOREACH_ID(_foreach_continue) \ + ? (void)++BOOST_FOREACH_ID(_foreach_cur) : (void)0) \ + if ( (BOOST_FOREACH_ID(_foreach_continue) = false) ) {} else \ + for (VAR = *BOOST_FOREACH_ID(_foreach_cur); \ + !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 \ @@ -1102,6 +1274,7 @@ BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_NEXT(COL) : (void)0) \ 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,7 +1283,28 @@ // all other respects, BOOST_REVERSE_FOREACH is like // BOOST_FOREACH. // -#define BOOST_REVERSE_FOREACH(VAR, COL) \ +#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING +# define BOOST_REVERSE_FOREACH(VAR, COL) \ + BOOST_FOREACH_PREAMBLE() \ + BOOST_FOREACH_AUTO_REF_REF( \ + BOOST_FOREACH_ID(_foreach_col) \ + , COL) \ + BOOST_FOREACH_AUTO_OBJECT( \ + BOOST_FOREACH_ID(_foreach_cur) \ + , boost::foreach_detail_::rbegin(BOOST_FOREACH_ID(_foreach_col))) \ + BOOST_FOREACH_AUTO_OBJECT( \ + BOOST_FOREACH_ID(_foreach_end) \ + , boost::foreach_detail_::rend(BOOST_FOREACH_ID(_foreach_col))) \ + for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \ + BOOST_FOREACH_ID(_foreach_continue) \ + && BOOST_FOREACH_ID(_foreach_cur) != BOOST_FOREACH_ID(_foreach_end); \ + BOOST_FOREACH_ID(_foreach_continue) \ + ? (void)++BOOST_FOREACH_ID(_foreach_cur) : (void)0) \ + if ( (BOOST_FOREACH_ID(_foreach_continue) = false) ) {} else \ + for (VAR = *BOOST_FOREACH_ID(_foreach_cur); \ + !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 \ @@ -1120,5 +1314,6 @@ BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_RNEXT(COL) : (void)0) \ if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) {} else \ for (VAR = BOOST_FOREACH_RDEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true) +#endif #endif