// Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/libs/foreach for documentation #ifndef BOOST_ADAPTED_FOREACH // MS compatible compilers support #pragma once #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif #include #include #include // Some compilers support rvalue references and auto type deduction. // With these C++0x features, temporary collections can be bound to // references and their lifetime is extended. No copy/move is needed. #if (!defined(BOOST_NO_AUTO_DECLARATIONS) || !defined(BOOST_NO_DECLTYPE)) \ && !defined(BOOST_NO_RVALUE_REFERENCES) # define BOOST_FOREACH_USE_REFERENCE_BINDING #endif #ifdef BOOST_FOREACH_USE_REFERENCE_BINDING 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; } template T const &add_const_if_rvalue(T &&); template typename remove_cv::type>::type decay_copy(T &&); }} # define BOOST_FOREACH_IS_RVALUE_(XXX) \ (true ? 0 : boost::foreach_detail_::is_rvalue(XXX)) /////////////////////////////////////////////////////////////////////////////// // BOOST_FOREACH_AUTO_REF(NAME, EXPR) // Equivalent to `auto const &NAME = EXPR`, if `EXPR` is an rvalue // `auto &NAME = EXPR`, if `EXPR` is an lvalue # if defined(BOOST_NO_DECLTYPE) # define BOOST_FOREACH_AUTO_REF(NAME, EXPR) \ if (bool BOOST_PP_CAT(NAME, _tmp_defined) = false) {} else \ for (auto &&BOOST_PP_CAT(NAME, _tmp) = (EXPR); \ !BOOST_PP_CAT(NAME, _tmp_defined); BOOST_PP_CAT(NAME, _tmp_defined) = true) \ if (bool BOOST_PP_CAT(NAME, _defined) = false) {} else \ for (auto &NAME = boost::foreach_detail_::add_const_if( \ BOOST_PP_CAT(NAME, _tmp) \ , BOOST_FOREACH_IS_RVALUE_(EXPR)); \ !BOOST_PP_CAT(NAME, _defined); BOOST_PP_CAT(NAME, _defined) = true) # else # define BOOST_FOREACH_AUTO_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) # endif /////////////////////////////////////////////////////////////////////////////// // BOOST_FOREACH_AUTO_OBJECT(NAME, EXPR) // Equivalent to `auto NAME = EXPR` # if defined(BOOST_NO_DECLTYPE) # define BOOST_FOREACH_AUTO_OBJECT(NAME, EXPR) \ if (bool BOOST_PP_CAT(NAME, _defined) = false) {} else \ for (auto NAME = (EXPR); \ !BOOST_PP_CAT(NAME, _defined); BOOST_PP_CAT(NAME, _defined) = true) # else # 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) # endif #else namespace boost { namespace foreach_detail_ { template inline typename type2type::type &get(auto_any_t col, type2type *, boost::mpl::true_ *) // rvalue { return auto_any_cast(col); } template inline typename type2type::type &get(auto_any_t col, type2type *, boost::mpl::false_ *) // lvalue { typedef typename type2type::type type; return derefof(auto_any_cast(col)); } # ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION template inline typename type2type::type &get(auto_any_t col, type2type *, bool *) { return *auto_any_cast, boost::mpl::false_>(col).get(); } # endif }} # define BOOST_FOREACH_GET(COL) \ boost::foreach_detail_::get( \ BOOST_FOREACH_ID(_foreach_pre_adapted_col) \ , BOOST_FOREACH_TYPEOF(COL) \ , BOOST_FOREACH_SHOULD_COPY(COL)) /////////////////////////////////////////////////////////////////////////////// // BOOST_FOREACH_AUTO_ANY(NAME, EXPR) // Equivalent to `auto_any_t NAME = EXPR` # define BOOST_FOREACH_AUTO_ANY(NAME, EXPR) \ if (boost::foreach_detail_::auto_any_t NAME = (EXPR)) {} else #endif /////////////////////////////////////////////////////////////////////////////// // BOOST_ADAPTED_FOREACH // // For iterating over adapted collections. Its main use is // when range adaptors are applied to a temporary container; // BOOST_ADAPTED_FOREACH extends the lifetime of the temporary // container, and so there is no dangling reference. // // BOOST_ADAPTED_FOREACH( // int i // , std::list(/*stuff*/) // , boost::adaptors::reversed) // { // /* // * the lifetime of the temporary list is extended. // */ // } // #ifdef BOOST_FOREACH_USE_REFERENCE_BINDING # define BOOST_ADAPTED_FOREACH(VAR, COL, ADP) \ BOOST_FOREACH_PREAMBLE() \ BOOST_FOREACH_AUTO_REF( \ BOOST_FOREACH_ID(_foreach_pre_adapted_col) \ , COL) \ BOOST_FOREACH_AUTO_REF( \ BOOST_FOREACH_ID(_foreach_col) \ , BOOST_FOREACH_ID(_foreach_pre_adapted_col) | ADP) \ BOOST_FOREACH_AUTO_OBJECT( \ BOOST_FOREACH_ID(_foreach_cur) \ , boost::begin(BOOST_FOREACH_ID(_foreach_col))) \ BOOST_FOREACH_AUTO_OBJECT( \ BOOST_FOREACH_ID(_foreach_end) \ , boost::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_ADAPTED_FOREACH(VAR, COL, ADP) \ BOOST_FOREACH_PREAMBLE() \ BOOST_FOREACH_AUTO_ANY( \ BOOST_FOREACH_ID(_foreach_pre_adapted_col) \ , BOOST_FOREACH_CONTAIN(COL)) \ BOOST_FOREACH_AUTO_ANY( \ BOOST_FOREACH_ID(_foreach_col) \ , BOOST_FOREACH_CONTAIN(BOOST_FOREACH_GET(COL) | ADP)) \ BOOST_FOREACH_AUTO_ANY( \ BOOST_FOREACH_ID(_foreach_cur) \ , BOOST_FOREACH_BEGIN(BOOST_FOREACH_GET(COL) | ADP)) \ BOOST_FOREACH_AUTO_ANY( \ BOOST_FOREACH_ID(_foreach_end) \ , BOOST_FOREACH_END(BOOST_FOREACH_GET(COL) | ADP)) \ for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \ BOOST_FOREACH_ID(_foreach_continue) \ && !BOOST_FOREACH_DONE(BOOST_FOREACH_GET(COL) | ADP); \ BOOST_FOREACH_ID(_foreach_continue) \ ? BOOST_FOREACH_NEXT(BOOST_FOREACH_GET(COL) | ADP) : (void)0) \ if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) {} else \ for (VAR = BOOST_FOREACH_DEREF(BOOST_FOREACH_GET(COL) | ADP); \ !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true) #endif #endif