diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..2d19fc7 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +*.html diff --git a/doc/reference/utilities.qbk b/doc/reference/utilities.qbk index ccad7b0..cde1720 100644 --- a/doc/reference/utilities.qbk +++ b/doc/reference/utilities.qbk @@ -273,6 +273,83 @@ sub_range sub = find_first( str, "ll" ); [endsect] +[section:combine Function combine] + +The `combine` function is used to make one range from multiple ranges. The +`combine` function returns a `combined_range` which is an `iterator_range` of +a `zip_iterator` from the Boost.Iterator library. + +[h4 Synopsis] + +`` +namespace boost +{ + namespace range + { + +template +class combined_range + : public iterator_range > +{ +public: + combined_range(IterTuple first, IterTuple last); +}; + +template +auto combine(Ranges&&... rngs) -> + combined_range + + } // namespace range +} // namespace boost +`` + +* [*Precondition:] For each type `r` in `Ranges`, `r` is a model of +__single_pass_range__ or better. +* [*Return Type:] `combined_range::type...> >` +* [*Returned Range Category:] The minimum of the range category of every range +`r` in `Ranges`. + +[h4 Example] + +`` +#include +#include +#include +#include +#include + +int main(int, const char*[]) +{ + std::vector v; + std::list l; + for (int i = 0; i < 5; ++i) + { + v.push_back(i); + l.push_back(static_cast(i) + 'a'); + } + + int ti; + char tc; + BOOST_FOREACH(boost::tie(ti, tc), boost::combine(v, l)) + { + std::cout << '(' << ti << ',' << tv << ')' << '\n'; + } + + return 0; +} +`` + +This produces the output: +`` +(0,a) +(1,b) +(2,c) +(3,d) +(4,e) +`` + +[endsect] + [section:join Function join] The intention of the `join` function is to join two ranges into one longer range. diff --git a/doc/upgrade.qbk b/doc/upgrade.qbk index ef66325..9bbf904 100644 --- a/doc/upgrade.qbk +++ b/doc/upgrade.qbk @@ -16,6 +16,8 @@ been noted that some calling code was relying on member functions such as due to `iterator_reference::type` not being a reference. The suggested refactoring is to use `boost::size(rng)`. +[endsect] + [section:upgrade_from_1_49 Upgrade from version 1.49] # __size__ now returns the type Rng::size_type if the range has size_type; diff --git a/include/boost/range/combine.hpp b/include/boost/range/combine.hpp index 999bbc3..26cef9a 100755 --- a/include/boost/range/combine.hpp +++ b/include/boost/range/combine.hpp @@ -9,296 +9,37 @@ #ifndef BOOST_RANGE_COMBINE_HPP #define BOOST_RANGE_COMBINE_HPP -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include namespace boost { - namespace range_detail + namespace range + { + +template +class combined_range + : public iterator_range > +{ + typedef iterator_range > base; +public: + combined_range(IterTuple first, IterTuple last) + : base(first, last) { - struct void_ { typedef void_ type; }; - } - - template<> struct range_iterator< ::boost::range_detail::void_ > - { - typedef ::boost::tuples::null_type type; - }; - - namespace range_detail - { - inline ::boost::tuples::null_type range_begin( ::boost::range_detail::void_& ) - { return ::boost::tuples::null_type(); } - - inline ::boost::tuples::null_type range_begin( const ::boost::range_detail::void_& ) - { return ::boost::tuples::null_type(); } - - inline ::boost::tuples::null_type range_end( ::boost::range_detail::void_& ) - { return ::boost::tuples::null_type(); } - - inline ::boost::tuples::null_type range_end( const ::boost::range_detail::void_& ) - { return ::boost::tuples::null_type(); } - - template< class T > - struct tuple_iter - { - typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::eval_if_c< - ::boost::is_same::value, - ::boost::mpl::identity< ::boost::tuples::null_type >, - ::boost::range_iterator - >::type type; - }; - - template< class Rng1, class Rng2 > - struct tuple_range - { - typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::eval_if_c< - ::boost::is_same::value, - ::boost::range_detail::void_, - ::boost::mpl::identity - >::type type; - }; - - template - < - class R1, - class R2, - class R3, - class R4, - class R5, - class R6 - > - struct generate_tuple - { - typedef ::boost::tuples::tuple< - BOOST_DEDUCED_TYPENAME tuple_iter::type, - BOOST_DEDUCED_TYPENAME tuple_iter::type, - BOOST_DEDUCED_TYPENAME tuple_iter::type, - BOOST_DEDUCED_TYPENAME tuple_iter::type, - BOOST_DEDUCED_TYPENAME tuple_iter::type, - BOOST_DEDUCED_TYPENAME tuple_iter::type - > type; - - static type begin( R1& r1, R2& r2, R3& r3, R4& r4, R5& r5, R6& r6 ) - { - return ::boost::tuples::make_tuple( ::boost::begin(r1), - ::boost::begin(r2), - ::boost::begin(r3), - ::boost::begin(r4), - ::boost::begin(r5), - ::boost::begin(r6) ); - } - - static type end( R1& r1, R2& r2, R3& r3, R4& r4, R5& r5, R6& r6 ) - { - return ::boost::tuples::make_tuple( ::boost::end(r1), - ::boost::end(r2), - ::boost::end(r3), - ::boost::end(r4), - ::boost::end(r5), - ::boost::end(r6) ); - } - }; - - template - < - class R1, - class R2 = void_, - class R3 = void_, - class R4 = void_, - class R5 = void_, - class R6 = void_ - > - struct zip_rng - : iterator_range< - zip_iterator< - BOOST_DEDUCED_TYPENAME generate_tuple::type - > - > - { - private: - typedef generate_tuple generator_t; - typedef BOOST_DEDUCED_TYPENAME generator_t::type tuple_t; - typedef zip_iterator zip_iter_t; - typedef iterator_range base_t; - - public: - zip_rng( R1& r1, R2& r2, R3& r3, R4& r4, R5& r5, R6& r6 ) - : base_t( zip_iter_t( generator_t::begin(r1,r2,r3,r4,r5,r6) ), - zip_iter_t( generator_t::end(r1,r2,r3,r4,r5,r6) ) ) - { - BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r2)); - BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r3)); - BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r4)); - BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r5)); - BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r6)); - } - - template< class Zip, class Rng > - zip_rng( Zip& z, Rng& r ) - : base_t( zip_iter_t( generator_t::begin( z, r ) ), - zip_iter_t( generator_t::end( z, r ) ) ) - { - - // @todo: tuple::begin( should be overloaded for this situation - } - - struct tuple_length : ::boost::tuples::length - { }; - - template< unsigned N > - struct get - { - template< class Z, class R > - static BOOST_DEDUCED_TYPENAME ::boost::tuples::element::type begin( Z& z, R& ) - { - return get( z.begin().get_iterator_tuple() ); - } - - template< class Z, class R > - static BOOST_DEDUCED_TYPENAME ::boost::tuples::element::type end( Z& z, R& r ) - { - return get( z.end().get_iterator_tuple() ); - } - }; - - }; - - template< class Rng1, class Rng2 > - struct zip_range - : iterator_range< - zip_iterator< - ::boost::tuples::tuple< - BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, - BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type - > - > - > - { - private: - typedef zip_iterator< - ::boost::tuples::tuple< - BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, - BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type - > - > zip_iter_t; - typedef iterator_range base_t; - - public: - zip_range( Rng1& r1, Rng2& r2 ) - : base_t( zip_iter_t( ::boost::tuples::make_tuple(::boost::begin(r1), - ::boost::begin(r2)) ), - zip_iter_t( ::boost::tuples::make_tuple(::boost::end(r1), - ::boost::end(r2)) ) ) - { - BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r2)); - } - }; - - template< class Rng1, class Rng2, class Rng3 > - struct zip_range3 - : iterator_range< - zip_iterator< - ::boost::tuples::tuple< - BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, - BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, - BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type - > - > - > - { - private: - typedef zip_iterator< - ::boost::tuples::tuple< - BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, - BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, - BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type - > - > zip_iter_t; - typedef iterator_range base_t; - - public: - zip_range3( Rng1& r1, Rng2& r2, Rng3& r3 ) - : base_t( zip_iter_t( ::boost::tuples::make_tuple(::boost::begin(r1), - ::boost::begin(r2), - ::boost::begin(r3)) ), - zip_iter_t( ::boost::tuples::make_tuple(::boost::end(r1), - ::boost::end(r2), - ::boost::end(r3)) ) - ) - { - BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r2)); - BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r3)); - } - }; - - - struct combine_tag {}; - - template< class Rng > - inline zip_rng - operator&( combine_tag, Rng& r ) - { - return zip_rng(r); - } - - template< class Rng > - inline iterator_range - operator&( combine_tag, const Rng& r ) - { - return iterator_range(r); - } - - template - < - class R1, - class R2, - class R3, - class R4, - class R5, - class Rng - > - inline BOOST_DEDUCED_TYPENAME zip_rng::next - operator&( const zip_rng& zip, - Rng& r ) - { - return zip_rng::next( zip, r ); - } - - } // namespace range_detail - - template< class Rng1, class Rng2 > - inline ::boost::range_detail::zip_range combine( Rng1& r1, Rng2& r2 ) - { - return ::boost::range_detail::zip_range(r1, r2); - } - - template< class Rng1, class Rng2 > - inline ::boost::range_detail::zip_range combine( const Rng1& r1, Rng2& r2 ) - { - return ::boost::range_detail::zip_range(r1, r2); - } - - template< class Rng1, class Rng2 > - inline ::boost::range_detail::zip_range combine( Rng1& r1, const Rng2& r2 ) - { - return ::boost::range_detail::zip_range(r1, r2); - } - - template< class Rng1, class Rng2 > - inline ::boost::range_detail::zip_range combine( const Rng1& r1, const Rng2& r2 ) - { - return ::boost::range_detail::zip_range(r1, r2); } +}; + } // namespace range } // namespace boost +#if defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) || \ + defined(BOOST_NO_CXX11_DECLTYPE) || \ + defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \ + defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +# include +#else +# include +#endif + #endif diff --git a/include/boost/range/const_iterator.hpp b/include/boost/range/const_iterator.hpp index 5512939..1cdbf03 100644 --- a/include/boost/range/const_iterator.hpp +++ b/include/boost/range/const_iterator.hpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -29,33 +30,45 @@ namespace boost // default ////////////////////////////////////////////////////////////////////////// - namespace range_detail { - BOOST_RANGE_EXTRACT_OPTIONAL_TYPE( const_iterator ) - } - - template< typename C > - struct range_const_iterator : range_detail::extract_const_iterator - {}; - - ////////////////////////////////////////////////////////////////////////// - // pair - ////////////////////////////////////////////////////////////////////////// - - template< typename Iterator > - struct range_const_iterator< std::pair > + namespace range_detail { - typedef Iterator type; - }; - - ////////////////////////////////////////////////////////////////////////// - // array - ////////////////////////////////////////////////////////////////////////// - template< typename T, std::size_t sz > - struct range_const_iterator< T[sz] > - { - typedef const T* type; - }; +BOOST_RANGE_EXTRACT_OPTIONAL_TYPE( const_iterator ) + +template< typename C > +struct range_const_iterator + : extract_const_iterator +{}; + +////////////////////////////////////////////////////////////////////////// +// pair +////////////////////////////////////////////////////////////////////////// + +template< typename Iterator > +struct range_const_iterator > +{ + typedef Iterator type; +}; + +////////////////////////////////////////////////////////////////////////// +// array +////////////////////////////////////////////////////////////////////////// + +template< typename T, std::size_t sz > +struct range_const_iterator< T[sz] > +{ + typedef const T* type; +}; + + } // namespace range_detail + +template +struct range_const_iterator + : range_detail::range_const_iterator< + typename remove_reference::type + > +{ +}; } // namespace boost diff --git a/include/boost/range/const_reverse_iterator.hpp b/include/boost/range/const_reverse_iterator.hpp index a1f49b7..d580aee 100644 --- a/include/boost/range/const_reverse_iterator.hpp +++ b/include/boost/range/const_reverse_iterator.hpp @@ -16,6 +16,7 @@ #endif #include +#include namespace boost { @@ -24,7 +25,8 @@ namespace boost // template< typename C > - struct range_const_reverse_iterator : range_reverse_iterator + struct range_const_reverse_iterator + : range_reverse_iterator::type> { }; } // namespace boost diff --git a/include/boost/range/detail/combine_cxx03.hpp b/include/boost/range/detail/combine_cxx03.hpp new file mode 100644 index 0000000..2040fe8 --- /dev/null +++ b/include/boost/range/detail/combine_cxx03.hpp @@ -0,0 +1,131 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_DETAIL_COMBINE_CXX03_HPP +#define BOOST_RANGE_DETAIL_COMBINE_CXX03_HPP + +#ifndef BOOST_RANGE_MIN_COMBINE_ARGS +#define BOOST_RANGE_MIN_COMBINE_ARGS 2 +#endif + +#ifndef BOOST_RANGE_MAX_COMBINE_ARGS +#define BOOST_RANGE_MAX_COMBINE_ARGS 5 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace boost +{ + namespace range_detail + { + +template +struct combined_result_impl; + +template +struct combined_result + : combined_result_impl::value> +{ +}; + +#define BOOST_RANGE_combined_element(z, n, data) \ + typename tuples::element::type + +#define BOOST_RANGE_combined_result(z, n, data) \ + template \ + struct combined_result_impl \ + : result_of \ + { \ + }; + +#define BOOST_PP_LOCAL_MACRO(n) BOOST_RANGE_combined_result(~,n,~) + +#define BOOST_PP_LOCAL_LIMITS (BOOST_RANGE_MIN_COMBINE_ARGS, \ + BOOST_RANGE_MAX_COMBINE_ARGS) +#include BOOST_PP_LOCAL_ITERATE() + +#define BOOST_RANGE_combined_get(z, n, data) get(tuple) + +#define BOOST_RANGE_combined_unpack(z, n, data) \ + template inline \ + typename combined_result::type \ + unpack_(mpl::int_, F f, const T& tuple) \ + { \ + return f(BOOST_PP_ENUM(n, BOOST_RANGE_combined_get, ~)); \ + } + +#define BOOST_PP_LOCAL_MACRO(n) BOOST_RANGE_combined_unpack(~,n,~) +#define BOOST_PP_LOCAL_LIMITS (BOOST_RANGE_MIN_COMBINE_ARGS, \ + BOOST_RANGE_MAX_COMBINE_ARGS) +#include BOOST_PP_LOCAL_ITERATE() + +} // namespace range_detail + +namespace range +{ + +#define BOOST_RANGE_combined_seq(z, n, data) boost::data(BOOST_PP_CAT(r,n)) + +#ifdef BOOST_NO_RVALUE_REFERENCES + +#include + +#else // by using rvalue references we avoid requiring 2^n overloads. + +#include + +#endif + +#define BOOST_PP_LOCAL_MACRO(n) BOOST_RANGE_combine(~,n,~) +#define BOOST_PP_LOCAL_LIMITS (BOOST_RANGE_MIN_COMBINE_ARGS, \ + BOOST_RANGE_MAX_COMBINE_ARGS) +#include BOOST_PP_LOCAL_ITERATE() + + } // namespace range + + using boost::range::combine; + +} // namespace boost + +#endif // include guard + +#undef BOOST_RANGE_combined_element +#undef BOOST_RANGE_combined_result +#undef BOOST_RANGE_combined_get +#undef BOOST_RANGE_combined_unpack +#undef BOOST_RANGE_combined_seq +#undef BOOST_RANGE_combined_exp_pred +#undef BOOST_RANGE_combined_exp_op +#undef BOOST_RANGE_combined_exp +#undef BOOST_RANGE_combined_bitset_pred +#undef BOOST_RANGE_combined_bitset_op +#undef BOOST_RANGE_combined_bitset +#undef BOOST_RANGE_combined_range_iterator +#undef BOOST_RANGE_combined_args +#undef BOOST_RANGE_combine_impl +#undef BOOST_RANGE_combine diff --git a/include/boost/range/detail/combine_cxx11.hpp b/include/boost/range/detail/combine_cxx11.hpp new file mode 100644 index 0000000..a7fa5b1 --- /dev/null +++ b/include/boost/range/detail/combine_cxx11.hpp @@ -0,0 +1,40 @@ +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_DETAIL_COMBINE_CXX11_HPP +#define BOOST_RANGE_DETAIL_COMBINE_CXX11_HPP + +#include +#include +#include +#include +#include + +#include + +namespace boost +{ + namespace range + { + +template +auto combine(Ranges&&... rngs) -> + combined_range +{ + return combined_range( + boost::make_tuple(boost::begin(rngs)...), + boost::make_tuple(boost::end(rngs)...)); +} + + } // namespace range + +using range::combine; + +} // namespace boost + +#endif // include guard diff --git a/include/boost/range/detail/combine_no_rvalue.hpp b/include/boost/range/detail/combine_no_rvalue.hpp new file mode 100644 index 0000000..bdb3950 --- /dev/null +++ b/include/boost/range/detail/combine_no_rvalue.hpp @@ -0,0 +1,73 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#define BOOST_RANGE_combined_exp_pred(d, data) BOOST_PP_TUPLE_ELEM(3, 0, data) + +#define BOOST_RANGE_combined_exp_op(d, data) \ + ( \ + BOOST_PP_DEC( \ + BOOST_PP_TUPLE_ELEM(3, 0, data) \ + ), \ + BOOST_PP_TUPLE_ELEM(3, 1, data), \ + BOOST_PP_MUL_D( \ + d, \ + BOOST_PP_TUPLE_ELEM(3, 2, data), \ + BOOST_PP_TUPLE_ELEM(3, 1, data) \ + ) \ + ) + +#define BOOST_RANGE_combined_exp(x, n) \ + BOOST_PP_TUPLE_ELEM(3, 2, \ + BOOST_PP_WHILE(BOOST_RANGE_combined_exp_pred, \ + BOOST_RANGE_combined_exp_op, (n, x, 1))) + +#define BOOST_RANGE_combined_bitset_pred(n, state) \ + BOOST_PP_TUPLE_ELEM(2,1,state) + +#define BOOST_RANGE_combined_bitset_op(d, state) \ + (BOOST_PP_DIV_D(d, BOOST_PP_TUPLE_ELEM(2,0,state), 2), \ + BOOST_PP_DEC(BOOST_PP_TUPLE_ELEM(2,1,state))) + +#define BOOST_RANGE_combined_bitset(i, n) \ +BOOST_PP_MOD(BOOST_PP_TUPLE_ELEM(2, 0, \ + BOOST_PP_WHILE(BOOST_RANGE_combined_bitset_pred, \ + BOOST_RANGE_combined_bitset_op, (i,n))), 2) + +#define BOOST_RANGE_combined_range_iterator(z, n, i) \ + typename range_iterator< \ + BOOST_PP_CAT(R,n) \ + BOOST_PP_IF( \ + BOOST_RANGE_combined_bitset(i,n), \ + BOOST_PP_IDENTITY(const), \ + BOOST_PP_EMPTY)() \ + >::type + +#define BOOST_RANGE_combined_args(z, n, i) \ + BOOST_PP_CAT(R, n) \ + BOOST_PP_IF(BOOST_RANGE_combined_bitset(i,n), const&, &) \ + BOOST_PP_CAT(r, n) + +#define BOOST_RANGE_combine_impl(z, i, n)\ + template \ + inline range::combined_range< \ + boost::tuple \ + > \ + combine(BOOST_PP_ENUM(n, BOOST_RANGE_combined_args, i)) \ + { \ + typedef tuple< \ + BOOST_PP_ENUM(n, BOOST_RANGE_combined_range_iterator, i) \ + > rng_tuple_t; \ + return range::combined_range( \ + rng_tuple_t(BOOST_PP_ENUM(n, BOOST_RANGE_combined_seq, begin)), \ + rng_tuple_t(BOOST_PP_ENUM(n, BOOST_RANGE_combined_seq, end))); \ + } + + +#define BOOST_RANGE_combine(z, n, data) \ + BOOST_PP_REPEAT(BOOST_RANGE_combined_exp(2,n), BOOST_RANGE_combine_impl, n) diff --git a/include/boost/range/detail/combine_rvalue.hpp b/include/boost/range/detail/combine_rvalue.hpp new file mode 100644 index 0000000..2e323b7 --- /dev/null +++ b/include/boost/range/detail/combine_rvalue.hpp @@ -0,0 +1,32 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#define BOOST_RANGE_combined_args(z, n, i) \ + BOOST_PP_CAT(R, n)&& BOOST_PP_CAT(r, n) + +#define BOOST_RANGE_combined_range_iterator(z, n, i) \ + typename range_iterator< \ + typename remove_reference::type \ + >::type + + +#define BOOST_RANGE_combine(z, n, data) \ + template \ + inline range::combined_range< \ + tuple \ + > \ + combine(BOOST_PP_ENUM(n, BOOST_RANGE_combined_args, ~)) \ + { \ + typedef tuple< \ + BOOST_PP_ENUM(n, BOOST_RANGE_combined_range_iterator, ~) \ + > rng_tuple_t; \ + return range::combined_range( \ + rng_tuple_t(BOOST_PP_ENUM(n, BOOST_RANGE_combined_seq, begin)), \ + rng_tuple_t(BOOST_PP_ENUM(n, BOOST_RANGE_combined_seq, end))); \ + } diff --git a/include/boost/range/iterator.hpp b/include/boost/range/iterator.hpp index 2966bdf..3ba9952 100644 --- a/include/boost/range/iterator.hpp +++ b/include/boost/range/iterator.hpp @@ -57,10 +57,15 @@ namespace boost #else - typedef BOOST_RANGE_DEDUCED_TYPENAME - mpl::eval_if_c< is_const::value, - range_const_iterator< typename remove_const::type >, - range_mutable_iterator >::type type; + private: + typedef typename remove_reference::type param_t; + + public: + typedef typename mpl::eval_if_c< + is_const::value, + range_const_iterator::type>, + range_mutable_iterator + >::type type; #endif }; diff --git a/test/combine.cpp b/test/combine.cpp index c020626..11f674b 100644 --- a/test/combine.cpp +++ b/test/combine.cpp @@ -1,5 +1,7 @@ // Boost.Range library // +// Copyright Neil Groves 2014 +// // Copyright Thorsten Ottosen 2006. Use, modification and // distribution is subject to the Boost Software License, Version // 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -7,65 +9,152 @@ // // For more information, see http://www.boost.org/libs/range/ // - #include + +#include + #include #include -#include #include #include - -struct add +namespace boost_range_test { - template< class T > - int operator()( const T& tuple ) const + namespace { - return boost::get<0>(tuple) + boost::get<1>(tuple); - } -}; -template< class CombinedRng > -void apply( const CombinedRng& r ) +template +void test_combine2() { std::vector v; - typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iterator_t; + std::list l; - iterator_t e = boost::end(r); - for (iterator_t i = boost::begin(r); i != e; ++i) + for (int i = 0; i < 10; ++i) { + v.push_back(i); + l.push_back(i * 2); + } + + ContRef1& in1 = v; + ContRef2& in2 = l; + + std::vector > output; + boost::push_back(output, boost::combine(in1, in2)); + + int index = 0; + int i1, i2; + BOOST_FOREACH(boost::tie(i1,i2), output) + { + BOOST_CHECK_EQUAL(i1, index); + BOOST_CHECK_EQUAL(i2, index * 2); + ++index; } } -void test_combine() +template +void test_combine3() { - std::vector v1, v2, v3; - for (int i = 1; i <= 4; ++i) + std::vector v1; + std::vector v2; + std::vector v3; + + for (int i = 0; i < 10; ++i) { v1.push_back(i); - v2.push_back(i); + v2.push_back(i * 2); + v3.push_back(i * 3); } - int i1, i2; - BOOST_FOREACH( boost::tie( i1, i2 ), boost::combine(v1,v2) ) + ContRef1& in1 = v1; + ContRef2& in2 = v2; + ContRef3& in3 = v3; + + std::vector > output; + boost::push_back(output, boost::combine(in1, in2, in3)); + + int index = 0; + int i1, i2, i3; + + BOOST_FOREACH(boost::tie(i1,i2,i3), output) { - v3.push_back( i1 + i2 ); + BOOST_CHECK_EQUAL(i1, index); + BOOST_CHECK_EQUAL(i2, index * 2); + BOOST_CHECK_EQUAL(i3, index * 3); + ++index; } - - BOOST_CHECK_EQUAL( v3.size(), v1.size() ); } + } // anonymous namespace +} // namespace boost_range_test - -using boost::unit_test::test_suite; - -test_suite* init_unit_test_suite( int argc, char* argv[] ) +boost::unit_test::test_suite* init_unit_test_suite(int, char*[] ) { - test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE( "Boost.Range combine() test suite" ); - test->add( BOOST_TEST_CASE( &test_combine ) ); + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine2< + const std::vector, const std::list >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine2< + const std::vector, std::list >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine2< + std::vector, const std::list >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine2< + std::vector, std::list >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + std::vector, + std::vector, + std::vector >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + std::vector, + std::vector, + const std::vector >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + std::vector, + const std::vector, + std::vector >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + std::vector, + const std::vector, + const std::vector >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + const std::vector, + std::vector, + std::vector >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + const std::vector, + std::vector, + const std::vector >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + const std::vector, + const std::vector, + std::vector >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + const std::vector, + const std::vector, + const std::vector >))); return test; } - -