Ticket #5475: foreach_cxx0x_v2.patch

File foreach_cxx0x_v2.patch, 12.8 KB (added by Michel MORIN <mimomorin@…>, 12 years ago)

A patch for foreach.hpp (against trunk) to bind temporary ranges to const rvalue references.

  • Boosty/boost-trunk/boost/foreach.hpp

     
    3030#include <boost/config.hpp>
    3131#include <boost/detail/workaround.hpp>
    3232
     33// Some compilers support rvalue references and auto type deduction.
     34// With these C++0x features, temporary collections can be bound to
     35// rvalue references and their lifetime is extended. No copy/move is needed.
     36#if !defined(BOOST_NO_DECLTYPE) && !defined(BOOST_NO_RVALUE_REFERENCES)
     37# define BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
    3338// Some compilers let us detect even const-qualified rvalues at compile-time
    34 #if !defined(BOOST_NO_RVALUE_REFERENCES)                                                         \
     39#elif !defined(BOOST_NO_RVALUE_REFERENCES)                                                       \
    3540 || BOOST_WORKAROUND(BOOST_MSVC, >= 1310) && !defined(_PREFAST_)                                 \
    3641 || (BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ <= 5) && !defined(BOOST_INTEL) &&       \
    3742                                                                  !defined(BOOST_CLANG))         \
     
    8893#include <boost/utility/addressof.hpp>
    8994#include <boost/foreach_fwd.hpp>
    9095
     96#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
     97# include <boost/type_traits/decay.hpp>
     98# include <boost/type_traits/remove_const.hpp>
     99# include <boost/type_traits/remove_cv.hpp>
     100#endif
     101
    91102#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
    92103# include <new>
    93104# include <boost/aligned_storage.hpp>
    94105# include <boost/utility/enable_if.hpp>
    95 # include <boost/type_traits/remove_const.hpp>
    96106#endif
    97107
    98108namespace boost
     
    689699}
    690700#endif
    691701
     702#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
     703template<typename T>
     704inline typename foreach_iterator<typename remove_const<T>::type, is_const<T> >::type
     705begin(T &col)
     706{
     707    return boost::begin(col);
     708}
     709
     710template<typename T>
     711inline T *
     712begin(T *&col)
     713{
     714    return col;
     715}
     716
     717template<typename T>
     718inline T *
     719begin(T * const &col)
     720{
     721    return col;
     722}
     723#endif
     724
    692725///////////////////////////////////////////////////////////////////////////////
    693726// end
    694727//
     
    729762}
    730763#endif
    731764
     765#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
     766template<typename T>
     767inline typename foreach_iterator<typename remove_const<T>::type, is_const<T> >::type
     768end(T &col)
     769{
     770    return boost::end(col);
     771}
     772
     773struct cstr_end_iterator
     774{
     775};
     776
     777template<typename T>
     778inline cstr_end_iterator
     779end(T *&col)
     780{
     781    return cstr_end_iterator();
     782}
     783
     784template<typename T>
     785inline cstr_end_iterator
     786end(T * const &col)
     787{
     788    return cstr_end_iterator();
     789}
     790#endif
     791
    732792///////////////////////////////////////////////////////////////////////////////
    733793// done
    734794//
     
    747807}
    748808#endif
    749809
     810#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
     811template<typename Iterator>
     812inline bool operator !=(Iterator cur, cstr_end_iterator)
     813{
     814    return *cur != 0;
     815}
     816#endif
     817
     818
    750819///////////////////////////////////////////////////////////////////////////////
    751820// next
    752821//
     
    811880}
    812881#endif
    813882
     883#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
     884template<typename T>
     885inline typename foreach_reverse_iterator<typename remove_const<T>::type, is_const<T> >::type
     886rbegin(T &col)
     887{
     888    return boost::rbegin(col);
     889}
     890
     891template<typename T>
     892inline reverse_iterator<T *>
     893rbegin(T *&col)
     894{
     895    T *p = col;
     896    while(0 != *p)
     897        ++p;
     898    return reverse_iterator<T *>(p);
     899}
     900
     901template<typename T>
     902inline reverse_iterator<T *>
     903rbegin(T * const &col)
     904{
     905    T *p = col;
     906    while(0 != *p)
     907        ++p;
     908    return reverse_iterator<T *>(p);
     909}
     910#endif
     911
    814912///////////////////////////////////////////////////////////////////////////////
    815913// rend
    816914//
     
    852950}
    853951#endif
    854952
     953#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
     954template<typename T>
     955inline typename foreach_reverse_iterator<typename remove_const<T>::type, is_const<T> >::type
     956rend(T &col)
     957{
     958    return boost::rend(col);
     959}
     960
     961template<typename T>
     962inline reverse_iterator<T *>
     963rend(T *&col)
     964{
     965    return reverse_iterator<T *>(col);
     966}
     967
     968template<typename T>
     969inline reverse_iterator<T *>
     970rend(T * const &col)
     971{
     972    return reverse_iterator<T *>(col);
     973}
     974#endif
     975
    855976///////////////////////////////////////////////////////////////////////////////
    856977// rdone
    857978//
     
    9221043            boost::foreach_detail_::to_ptr(COL)                                                 \
    9231044          , boost_foreach_argument_dependent_lookup_hack_value))
    9241045
    925 #if defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION)
    9261046///////////////////////////////////////////////////////////////////////////////
     1047// R-values and const R-values are bound to rvalue references
     1048///////////////////////////////////////////////////////////////////////////////
     1049#if defined(BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING)
     1050# define BOOST_FOREACH_PREAMBLE()                                                               \
     1051    BOOST_FOREACH_SUPPRESS_WARNINGS()
     1052
     1053namespace boost { namespace foreach_detail_
     1054{
     1055    template<typename T>
     1056    typename remove_cv<typename decay<T>::type>::type decay_copy(T &&);
     1057   
     1058    template<typename T>
     1059    T const add_const_if_rvalue(T &&);
     1060}}
     1061# define BOOST_FOREACH_AUTO_OBJECT(NAME, EXPR)                                                                    \
     1062    if (bool BOOST_PP_CAT(NAME, _defined) = false) {} else                                                        \
     1063    for (decltype(boost::foreach_detail_::decay_copy(EXPR)) NAME = (EXPR);                                        \
     1064        !BOOST_PP_CAT(NAME, _defined); BOOST_PP_CAT(NAME, _defined) = true)
     1065
     1066// If EXPR is an rvalue, bind it to a const rvalue reference.
     1067# define BOOST_FOREACH_AUTO_REF_REF(NAME, EXPR)                                                                   \
     1068    if (bool BOOST_PP_CAT(NAME, _defined) = false) {} else                                                        \
     1069    for (decltype(boost::foreach_detail_::add_const_if_rvalue(EXPR)) &&NAME = (EXPR);                             \
     1070        !BOOST_PP_CAT(NAME, _defined); BOOST_PP_CAT(NAME, _defined) = true)
     1071
     1072#elif defined(BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION)
     1073///////////////////////////////////////////////////////////////////////////////
    9271074// R-values and const R-values supported here with zero runtime overhead
    9281075///////////////////////////////////////////////////////////////////////////////
     1076# define BOOST_FOREACH_PREAMBLE()                                                               \
     1077    BOOST_FOREACH_SUPPRESS_WARNINGS()
    9291078
     1079
     1080
    9301081// No variable is needed to track the rvalue-ness of the collection expression
    9311082# define BOOST_FOREACH_PREAMBLE()                                                               \
    9321083    BOOST_FOREACH_SUPPRESS_WARNINGS()
     
    10921243//   BOOST_FOREACH(i, int_list)
    10931244//       { ... }
    10941245//
    1095 #define BOOST_FOREACH(VAR, COL)                                                                                   \
     1246#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
     1247# define BOOST_FOREACH(VAR, COL)                                                                \
     1248    BOOST_FOREACH_PREAMBLE()                                                                    \
     1249    BOOST_FOREACH_AUTO_REF_REF(                                                                 \
     1250        BOOST_FOREACH_ID(_foreach_col)                                                          \
     1251      , COL)                                                                                    \
     1252    BOOST_FOREACH_AUTO_OBJECT(                                                                  \
     1253        BOOST_FOREACH_ID(_foreach_cur)                                                          \
     1254      , boost::foreach_detail_::begin(BOOST_FOREACH_ID(_foreach_col)))                          \
     1255    BOOST_FOREACH_AUTO_OBJECT(                                                                  \
     1256        BOOST_FOREACH_ID(_foreach_end)                                                          \
     1257      , boost::foreach_detail_::end(BOOST_FOREACH_ID(_foreach_col)))                            \
     1258    for (bool BOOST_FOREACH_ID(_foreach_continue) = true;                                       \
     1259              BOOST_FOREACH_ID(_foreach_continue)                                               \
     1260               && BOOST_FOREACH_ID(_foreach_cur) != BOOST_FOREACH_ID(_foreach_end);             \
     1261              BOOST_FOREACH_ID(_foreach_continue)                                               \
     1262                ? (void)++BOOST_FOREACH_ID(_foreach_cur) : (void)0)                             \
     1263        if ( (BOOST_FOREACH_ID(_foreach_continue) = false) ) {} else                            \
     1264        for (VAR = *BOOST_FOREACH_ID(_foreach_cur);                                             \
     1265                   !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true)
     1266#else
     1267# define BOOST_FOREACH(VAR, COL)                                                                                  \
    10961268    BOOST_FOREACH_PREAMBLE()                                                                                      \
    10971269    if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL)) {} else   \
    10981270    if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_BEGIN(COL)) {} else     \
     
    11021274              BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_NEXT(COL) : (void)0)                            \
    11031275        if  (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) {} else                      \
    11041276        for (VAR = BOOST_FOREACH_DEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true)
     1277#endif
    11051278
    11061279///////////////////////////////////////////////////////////////////////////////
    11071280// BOOST_REVERSE_FOREACH
     
    11101283//   all other respects, BOOST_REVERSE_FOREACH is like
    11111284//   BOOST_FOREACH.
    11121285//
    1113 #define BOOST_REVERSE_FOREACH(VAR, COL)                                                                           \
     1286#ifdef BOOST_FOREACH_USE_RVALUE_REFERENCE_BINDING
     1287# define BOOST_REVERSE_FOREACH(VAR, COL)                                                        \
     1288    BOOST_FOREACH_PREAMBLE()                                                                    \
     1289    BOOST_FOREACH_AUTO_REF_REF(                                                                 \
     1290        BOOST_FOREACH_ID(_foreach_col)                                                          \
     1291      , COL)                                                                                    \
     1292    BOOST_FOREACH_AUTO_OBJECT(                                                                  \
     1293        BOOST_FOREACH_ID(_foreach_cur)                                                          \
     1294      , boost::foreach_detail_::rbegin(BOOST_FOREACH_ID(_foreach_col)))                         \
     1295    BOOST_FOREACH_AUTO_OBJECT(                                                                  \
     1296        BOOST_FOREACH_ID(_foreach_end)                                                          \
     1297      , boost::foreach_detail_::rend(BOOST_FOREACH_ID(_foreach_col)))                           \
     1298    for (bool BOOST_FOREACH_ID(_foreach_continue) = true;                                       \
     1299              BOOST_FOREACH_ID(_foreach_continue)                                               \
     1300               && BOOST_FOREACH_ID(_foreach_cur) != BOOST_FOREACH_ID(_foreach_end);             \
     1301              BOOST_FOREACH_ID(_foreach_continue)                                               \
     1302                ? (void)++BOOST_FOREACH_ID(_foreach_cur) : (void)0)                             \
     1303        if ( (BOOST_FOREACH_ID(_foreach_continue) = false) ) {} else                            \
     1304        for (VAR = *BOOST_FOREACH_ID(_foreach_cur);                                             \
     1305                   !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true)
     1306#else
     1307# define BOOST_REVERSE_FOREACH(VAR, COL)                                                                          \
    11141308    BOOST_FOREACH_PREAMBLE()                                                                                      \
    11151309    if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL)) {} else   \
    11161310    if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_RBEGIN(COL)) {} else    \
     
    11201314              BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_RNEXT(COL) : (void)0)                           \
    11211315        if  (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) {} else                      \
    11221316        for (VAR = BOOST_FOREACH_RDEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true)
     1317#endif
    11231318
    11241319#endif