diff --git a/doc/concepts.qbk b/doc/concepts.qbk index f379e18..e0b5f41 100644 --- a/doc/concepts.qbk +++ b/doc/concepts.qbk @@ -7,7 +7,7 @@ [section Overview] -A Range is a [*/concept/] similar to the STL [@http://www.sgi.com/Technology/STL/Container.html Container] concept. A Range provides iterators for accessing a half-open range `[first,one_past_last)` of elements and provides information about the number of elements in the Range. However, a Range has fewer requirements than a Container. +A Range is a [*/concept/] similar to the STL [@http://www.sgi.com/tech/stl/Container.html Container] concept. A Range provides iterators for accessing a half-open range `[first,one_past_last)` of elements and provides information about the number of elements in the Range. However, a Range has fewer requirements than a Container. The motivation for the Range concept is that there are many useful Container-like types that do not meet the full requirements of Container, and many algorithms that can be written with this reduced set of requirements. In particular, a Range does not necessarily diff --git a/doc/headers.qbk b/doc/headers.qbk index 3107018..2e5ae02 100644 --- a/doc/headers.qbk +++ b/doc/headers.qbk @@ -46,7 +46,7 @@ [[``] [__range_adaptors_copied__]] [[``] [__range_adaptors_filtered__]] [[``] [__range_adaptors_indexed__]] - [[``] [__range_adaptors_indirected__]] [[``] [__range_adaptors_map_keys__ __range_adaptors_map_values__]] [[``] [__range_adaptors_replaced__]] [[``] [__range_adaptors_replaced_if__]] diff --git a/doc/reference/adaptors.qbk b/doc/reference/adaptors.qbk index b3efaee..2cead36 100644 --- a/doc/reference/adaptors.qbk +++ b/doc/reference/adaptors.qbk @@ -172,6 +172,7 @@ rng | boost::adaptors::adaptor_generator [include adaptors/indirected.qbk] [include adaptors/map_keys.qbk] [include adaptors/map_values.qbk] +[include adaptors/ref_unwrapped.qbk] [include adaptors/replaced.qbk] [include adaptors/replaced_if.qbk] [include adaptors/reversed.qbk] diff --git a/doc/reference/adaptors/ref_unwrapped.qbk b/doc/reference/adaptors/ref_unwrapped.qbk new file mode 100644 index 0000000..156ad67 --- /dev/null +++ b/doc/reference/adaptors/ref_unwrapped.qbk @@ -0,0 +1,32 @@ +[/ + Copyright 2015 Robin Eckert + 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) +/] +[section:ref_unwrapped ref_unwrapped] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::ref_unwrapped`]] + [[Function] [`boost::adaptors::ref_unwrap(rng)`]] +] + +This adaptor produces a range than applies `.get()` on all values in +the range. It is useful for iterating ranges of +`std::reference_wrapper` values or values using similar semantics. + +The adaptor is C++11 (and above) only. + +* [*Precondition:] The `value_type` of the range has a `.get() const`. +* [*Postcondition:] For all elements `x` in the returned range, `x` is the result of `y.get()` where `y` is the corresponding element in the original range. +* [*Range Category:] __single_pass_range__ +* [*Range Return Type:] `boost::unwrap_ref_range` +* [*Returned Range Category:] The range category of `rng`. + +[section:ref_unwrapped_example ref_unwrapped example] +[import ../../../test/adaptor_test/ref_unwrapped_example.cpp] +[ref_unwrapped_example] +[endsect] + +This would produce the output `123`. +[endsect] diff --git a/doc/reference/adaptors/replaced.qbk b/doc/reference/adaptors/replaced.qbk index 3afb2c5..1c34ab9 100644 --- a/doc/reference/adaptors/replaced.qbk +++ b/doc/reference/adaptors/replaced.qbk @@ -7,8 +7,8 @@ [table [[Syntax] [Code]] - [[Pipe] [`rng | boost::adaptors::replaced(new_value, old_value)`]] - [[Function] [`boost::adaptors::replace(rng, new_value, old_value)`]] + [[Pipe] [`rng | boost::adaptors::replaced(old_value, new_value)`]] + [[Function] [`boost::adaptors::replace(rng, old_value, new_value)`]] ] * [*Precondition:] diff --git a/doc/reference/ranges/irange.qbk b/doc/reference/ranges/irange.qbk index 6e59cb1..1d4ae7e 100644 --- a/doc/reference/ranges/irange.qbk +++ b/doc/reference/ranges/irange.qbk @@ -10,7 +10,11 @@ `` template iterator_range< range_detail::integer_iterator > -irange(Integer first, Integer last); +irange(Integer last); + +template +iterator_range< range_detail::integer_iterator > +irange(Integer first, Integer last); template iterator_range< range_detail::integer_iterator_with_step > @@ -37,4 +41,3 @@ Defined in the header file `boost/range/irange.hpp` Constant. Since this function generates a new range the most significant performance cost is incurred through the iteration of the generated range. [endsect] - diff --git a/include/boost/range/adaptor/adjacent_filtered.hpp b/include/boost/range/adaptor/adjacent_filtered.hpp index 287a4ae..405fe7b 100644 --- a/include/boost/range/adaptor/adjacent_filtered.hpp +++ b/include/boost/range/adaptor/adjacent_filtered.hpp @@ -181,7 +181,7 @@ namespace boost } template< class ForwardRng, class BinPredicate > - inline adjacent_filtered_range + inline adjacent_filtered_range operator|( const ForwardRng& r, const adjacent_excl_holder& f ) { diff --git a/include/boost/range/adaptor/ref_unwrapped.hpp b/include/boost/range/adaptor/ref_unwrapped.hpp new file mode 100644 index 0000000..71af483 --- /dev/null +++ b/include/boost/range/adaptor/ref_unwrapped.hpp @@ -0,0 +1,102 @@ +// Boost.Range library +// +// Copyright Robin Eckert 2015. +// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. 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_ADAPTOR_REF_UNWRAPPED_HPP +#define BOOST_RANGE_ADAPTOR_REF_UNWRAPPED_HPP + +#include +#include +#include + +#include + +#if !defined(BOOST_NO_CXX11_DECLTYPE) + +namespace boost +{ + namespace range_detail + { + struct ref_unwrapped_forwarder {}; + + template + struct unwrap_ref + { + typedef BOOST_DEDUCED_TYPENAME + range_reference::type argument_type; + + using result_type = decltype(std::declval().get() ); + + result_type operator()( argument_type &&r ) const + { + return r.get(); + } + }; + + + template + class unwrap_ref_range + : public transformed_range, + SinglePassRange> + { + using base = transformed_range, + SinglePassRange>; + public: + using transform_fn_type = unwrap_ref; + using source_range_type = SinglePassRange; + + unwrap_ref_range(transform_fn_type fn, source_range_type &rng) + : base(fn, rng) + { + } + + unwrap_ref_range(const base &other) : base(other) {} + }; + + template + inline unwrap_ref_range + operator|(SinglePassRange& r, ref_unwrapped_forwarder) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return operator|( r, + boost::adaptors::transformed(unwrap_ref())); + } + + } + + using range_detail::unwrap_ref_range; + + namespace adaptors + { + namespace + { + const range_detail::ref_unwrapped_forwarder ref_unwrapped = + range_detail::ref_unwrapped_forwarder(); + } + + template + inline unwrap_ref_range + ref_unwrap(SinglePassRange& rng) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return unwrap_ref_range( + range_detail::unwrap_ref(), rng ); + } + } // 'adaptors' + +} + +#endif + +#endif diff --git a/include/boost/range/adaptor/replaced.hpp b/include/boost/range/adaptor/replaced.hpp index 1950b82..42eb52a 100644 --- a/include/boost/range/adaptor/replaced.hpp +++ b/include/boost/range/adaptor/replaced.hpp @@ -101,12 +101,9 @@ namespace boost void operator=(const replace_holder&); }; - template< class SinglePassRange > + template< class SinglePassRange, class Value > inline replaced_range - operator|( - SinglePassRange& r, - const replace_holder< - BOOST_DEDUCED_TYPENAME range_value::type>& f ) + operator|(SinglePassRange& r, const replace_holder& f) { BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept)); @@ -114,12 +111,9 @@ namespace boost return replaced_range(r, f.val1, f.val2); } - template< class SinglePassRange > + template< class SinglePassRange, class Value > inline replaced_range - operator|( - const SinglePassRange& r, - const replace_holder< - BOOST_DEDUCED_TYPENAME range_value::type>& f) + operator|(const SinglePassRange& r, const replace_holder& f) { BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept)); @@ -139,11 +133,9 @@ namespace boost range_detail::forwarder2(); } - template + template< class SinglePassRange, class Value > inline replaced_range - replace(SinglePassRange& rng, - BOOST_DEDUCED_TYPENAME range_value::type from, - BOOST_DEDUCED_TYPENAME range_value::type to) + replace(SinglePassRange& rng, Value from, Value to) { BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept)); @@ -151,11 +143,9 @@ namespace boost return replaced_range(rng, from, to); } - template + template< class SinglePassRange, class Value > inline replaced_range - replace(const SinglePassRange& rng, - BOOST_DEDUCED_TYPENAME range_value::type from, - BOOST_DEDUCED_TYPENAME range_value::type to) + replace(const SinglePassRange& rng, Value from, Value to) { BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept)); diff --git a/include/boost/range/adaptor/replaced_if.hpp b/include/boost/range/adaptor/replaced_if.hpp index e425e7d..83d3ec8 100644 --- a/include/boost/range/adaptor/replaced_if.hpp +++ b/include/boost/range/adaptor/replaced_if.hpp @@ -103,13 +103,9 @@ namespace boost T m_to; }; - template< class Pred, class SinglePassRange > + template< class Pred, class SinglePassRange, class Value > inline replaced_if_range - operator|( - SinglePassRange& r, - const replace_if_holder< - Pred, - BOOST_DEDUCED_TYPENAME range_value::type>& f) + operator|(SinglePassRange& r, const replace_if_holder& f) { BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept)); @@ -118,13 +114,9 @@ namespace boost r, f.pred(), f.to()); } - template< class Pred, class SinglePassRange > + template< class Pred, class SinglePassRange, class Value > inline replaced_if_range - operator|( - const SinglePassRange& r, - const replace_if_holder< - Pred, - BOOST_DEDUCED_TYPENAME range_value::type>& f) + operator|(const SinglePassRange& r, const replace_if_holder& f) { BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept)); @@ -145,10 +137,9 @@ namespace boost range_detail::forwarder2TU(); } - template + template< class Pred, class SinglePassRange, class Value > inline replaced_if_range - replace_if(SinglePassRange& rng, Pred pred, - BOOST_DEDUCED_TYPENAME range_value::type to) + replace_if(SinglePassRange& rng, Pred pred, Value to) { BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept)); @@ -157,12 +148,9 @@ namespace boost rng, pred, to); } - template + template< class Pred, class SinglePassRange, class Value > inline replaced_if_range - replace_if( - const SinglePassRange& rng, - Pred pred, - BOOST_DEDUCED_TYPENAME range_value::type to) + replace_if(const SinglePassRange& rng, Pred pred, Value to) { BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept)); diff --git a/include/boost/range/algorithm/max_element.hpp b/include/boost/range/algorithm/max_element.hpp index a0c1ffd..dd2b9cb 100644 --- a/include/boost/range/algorithm/max_element.hpp +++ b/include/boost/range/algorithm/max_element.hpp @@ -9,12 +9,12 @@ #ifndef BOOST_RANGE_ALGORITHM_MAX_ELEMENT_HPP_INCLUDED #define BOOST_RANGE_ALGORITHM_MAX_ELEMENT_HPP_INCLUDED +#include #include #include #include #include #include -#include namespace boost { @@ -32,7 +32,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator::type max_element(ForwardRange& rng) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::max_element(boost::begin(rng), boost::end(rng)); + return boost::first_max_element(boost::begin(rng), boost::end(rng)); } /// \overload @@ -41,7 +41,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator::type max_element(const ForwardRange& rng) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::max_element(boost::begin(rng), boost::end(rng)); + return boost::first_max_element(boost::begin(rng), boost::end(rng)); } /// \overload @@ -50,7 +50,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator::type max_element(ForwardRange& rng, BinaryPredicate pred) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::max_element(boost::begin(rng), boost::end(rng), pred); + return boost::first_max_element(boost::begin(rng), boost::end(rng), pred); } /// \overload @@ -59,7 +59,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator::type max_element(const ForwardRange& rng, BinaryPredicate pred) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::max_element(boost::begin(rng), boost::end(rng), pred); + return boost::first_max_element(boost::begin(rng), boost::end(rng), pred); } // range_return overloads @@ -71,7 +71,7 @@ max_element(ForwardRange& rng) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); return range_return::pack( - std::max_element(boost::begin(rng), boost::end(rng)), + boost::first_max_element(boost::begin(rng), boost::end(rng)), rng); } @@ -82,7 +82,7 @@ max_element(const ForwardRange& rng) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); return range_return::pack( - std::max_element(boost::begin(rng), boost::end(rng)), + boost::first_max_element(boost::begin(rng), boost::end(rng)), rng); } @@ -93,7 +93,7 @@ max_element(ForwardRange& rng, BinaryPredicate pred) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); return range_return::pack( - std::max_element(boost::begin(rng), boost::end(rng), pred), + boost::first_max_element(boost::begin(rng), boost::end(rng), pred), rng); } @@ -104,7 +104,7 @@ max_element(const ForwardRange& rng, BinaryPredicate pred) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); return range_return::pack( - std::max_element(boost::begin(rng), boost::end(rng), pred), + boost::first_max_element(boost::begin(rng), boost::end(rng), pred), rng); } diff --git a/include/boost/range/algorithm/min_element.hpp b/include/boost/range/algorithm/min_element.hpp index c966b1e..339f56a 100644 --- a/include/boost/range/algorithm/min_element.hpp +++ b/include/boost/range/algorithm/min_element.hpp @@ -9,12 +9,12 @@ #ifndef BOOST_RANGE_ALGORITHM_MIN_ELEMENT_HPP_INCLUDED #define BOOST_RANGE_ALGORITHM_MIN_ELEMENT_HPP_INCLUDED +#include #include #include #include #include #include -#include namespace boost { @@ -32,7 +32,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator::type min_element(ForwardRange& rng) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::min_element(boost::begin(rng), boost::end(rng)); + return boost::first_min_element(boost::begin(rng), boost::end(rng)); } /// \overload @@ -41,7 +41,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator::type min_element(const ForwardRange& rng) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::min_element(boost::begin(rng), boost::end(rng)); + return boost::first_min_element(boost::begin(rng), boost::end(rng)); } /// \overload @@ -50,7 +50,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator::type min_element(ForwardRange& rng, BinaryPredicate pred) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::min_element(boost::begin(rng), boost::end(rng), pred); + return boost::first_min_element(boost::begin(rng), boost::end(rng), pred); } /// \overload @@ -59,7 +59,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator::type min_element(const ForwardRange& rng, BinaryPredicate pred) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::min_element(boost::begin(rng), boost::end(rng), pred); + return boost::first_min_element(boost::begin(rng), boost::end(rng), pred); } // range_return overloads @@ -71,7 +71,7 @@ min_element(ForwardRange& rng) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); return range_return::pack( - std::min_element(boost::begin(rng), boost::end(rng)), + boost::first_min_element(boost::begin(rng), boost::end(rng)), rng); } @@ -82,7 +82,7 @@ min_element(const ForwardRange& rng) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); return range_return::pack( - std::min_element(boost::begin(rng), boost::end(rng)), + boost::first_min_element(boost::begin(rng), boost::end(rng)), rng); } @@ -93,7 +93,7 @@ min_element(ForwardRange& rng, BinaryPredicate pred) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); return range_return::pack( - std::min_element(boost::begin(rng), boost::end(rng), pred), + boost::first_min_element(boost::begin(rng), boost::end(rng), pred), rng); } @@ -104,7 +104,7 @@ min_element(const ForwardRange& rng, BinaryPredicate pred) { BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); return range_return::pack( - std::min_element(boost::begin(rng), boost::end(rng), pred), + boost::first_min_element(boost::begin(rng), boost::end(rng), pred), rng); } diff --git a/include/boost/range/algorithm/random_shuffle.hpp b/include/boost/range/algorithm/random_shuffle.hpp index 95bbd97..2475173 100644 --- a/include/boost/range/algorithm/random_shuffle.hpp +++ b/include/boost/range/algorithm/random_shuffle.hpp @@ -14,12 +14,85 @@ #include #include #include +#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE +#include +#endif namespace boost { namespace range { + namespace detail + { +#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE + +// wrap std::rand as UniformRandomBitGenerator +struct wrap_rand +{ + typedef unsigned int result_type; + + static result_type (min)() + { + return 0; + } + + static result_type (max)() + { + return RAND_MAX; + } + + result_type operator()() + { + return std::rand(); + } +}; + +template< class RandomIt > +inline void random_shuffle(RandomIt first, RandomIt last) +{ + std::shuffle(first, last, wrap_rand()); +} + +// wrap Generator as UniformRandomBitGenerator +template< class Generator > +struct wrap_generator +{ + typedef unsigned int result_type; + static const int max_arg = ((0u - 1u) >> 2) + 1; + Generator& g; + + wrap_generator(Generator& gen) : g(gen) {} + + static result_type (min)() + { + return 0; + } + + static result_type (max)() + { + return max_arg - 1; + } + + result_type operator()() + { + return static_cast(g(max_arg)); + } +}; + +template< class RandomIt, class Generator > +inline void random_shuffle(RandomIt first, RandomIt last, Generator& gen) +{ + std::shuffle(first, last, wrap_generator< Generator >(gen)); +} + +#else + +using std::random_shuffle; + +#endif + } // namespace detail + /// \brief template function random_shuffle /// /// range-based version of the random_shuffle std algorithm @@ -30,7 +103,7 @@ template inline RandomAccessRange& random_shuffle(RandomAccessRange& rng) { BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::random_shuffle(boost::begin(rng), boost::end(rng)); + detail::random_shuffle(boost::begin(rng), boost::end(rng)); return rng; } @@ -39,7 +112,7 @@ template inline const RandomAccessRange& random_shuffle(const RandomAccessRange& rng) { BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::random_shuffle(boost::begin(rng), boost::end(rng)); + detail::random_shuffle(boost::begin(rng), boost::end(rng)); return rng; } @@ -48,7 +121,7 @@ template inline RandomAccessRange& random_shuffle(RandomAccessRange& rng, Generator& gen) { BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::random_shuffle(boost::begin(rng), boost::end(rng), gen); + detail::random_shuffle(boost::begin(rng), boost::end(rng), gen); return rng; } @@ -57,7 +130,7 @@ template inline const RandomAccessRange& random_shuffle(const RandomAccessRange& rng, Generator& gen) { BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::random_shuffle(boost::begin(rng), boost::end(rng), gen); + detail::random_shuffle(boost::begin(rng), boost::end(rng), gen); return rng; } diff --git a/include/boost/range/algorithm_ext/insert.hpp b/include/boost/range/algorithm_ext/insert.hpp index c0c04c8..51f1b8e 100644 --- a/include/boost/range/algorithm_ext/insert.hpp +++ b/include/boost/range/algorithm_ext/insert.hpp @@ -39,6 +39,7 @@ inline Container& insert( Container& on, const Range& from ) BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); on.insert(boost::begin(from), boost::end(from)); + return on; } } // namespace range diff --git a/include/boost/range/as_literal.hpp b/include/boost/range/as_literal.hpp index 1c16e4a..3bca1a8 100644 --- a/include/boost/range/as_literal.hpp +++ b/include/boost/range/as_literal.hpp @@ -25,6 +25,11 @@ #include #include + +#if !defined(BOOST_NO_CXX11_CHAR16_T) || !defined(BOOST_NO_CXX11_CHAR32_T) +#include // for std::char_traits +#endif + #ifndef BOOST_NO_CWCHAR #include #endif @@ -38,6 +43,20 @@ namespace boost return strlen( s ); } +#ifndef BOOST_NO_CXX11_CHAR16_T + inline std::size_t length( const char16_t* s ) + { + return std::char_traits::length( s ); + } +#endif + +#ifndef BOOST_NO_CXX11_CHAR32_T + inline std::size_t length( const char32_t* s ) + { + return std::char_traits::length( s ); + } +#endif + #ifndef BOOST_NO_CWCHAR inline std::size_t length( const wchar_t* s ) { @@ -61,6 +80,30 @@ namespace boost return true; } +#ifndef BOOST_NO_CXX11_CHAR16_T + inline bool is_char_ptr( char16_t* ) + { + return true; + } + + inline bool is_char_ptr( const char16_t* ) + { + return true; + } +#endif + +#ifndef BOOST_NO_CXX11_CHAR32_T + inline bool is_char_ptr( char32_t* ) + { + return true; + } + + inline bool is_char_ptr( const char32_t* ) + { + return true; + } +#endif + #ifndef BOOST_NO_CWCHAR inline bool is_char_ptr( wchar_t* ) { diff --git a/include/boost/range/begin.hpp b/include/boost/range/begin.hpp index ba5a73b..0d7d3db 100644 --- a/include/boost/range/begin.hpp +++ b/include/boost/range/begin.hpp @@ -36,7 +36,7 @@ namespace range_detail ////////////////////////////////////////////////////////////////////// template< typename C > - inline BOOST_DEDUCED_TYPENAME range_iterator::type + BOOST_CONSTEXPR inline BOOST_DEDUCED_TYPENAME range_iterator::type range_begin( C& c ) { // @@ -52,13 +52,13 @@ namespace range_detail ////////////////////////////////////////////////////////////////////// template< typename Iterator > - inline Iterator range_begin( const std::pair& p ) + BOOST_CONSTEXPR inline Iterator range_begin( const std::pair& p ) { return p.first; } template< typename Iterator > - inline Iterator range_begin( std::pair& p ) + BOOST_CONSTEXPR inline Iterator range_begin( std::pair& p ) { return p.first; } @@ -71,13 +71,13 @@ namespace range_detail // May this be discarded? Or is it needed for bad compilers? // template< typename T, std::size_t sz > - inline const T* range_begin( const T (&a)[sz] ) + BOOST_CONSTEXPR inline const T* range_begin( const T (&a)[sz] ) BOOST_NOEXCEPT { return a; } template< typename T, std::size_t sz > - inline T* range_begin( T (&a)[sz] ) + BOOST_CONSTEXPR inline T* range_begin( T (&a)[sz] ) BOOST_NOEXCEPT { return a; } @@ -94,7 +94,7 @@ namespace range_adl_barrier { template< class T > -inline BOOST_DEDUCED_TYPENAME range_iterator::type begin( T& r ) +BOOST_CONSTEXPR inline BOOST_DEDUCED_TYPENAME range_iterator::type begin( T& r ) { #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) using namespace range_detail; @@ -103,7 +103,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator::type begin( T& r ) } template< class T > -inline BOOST_DEDUCED_TYPENAME range_iterator::type begin( const T& r ) +BOOST_CONSTEXPR inline BOOST_DEDUCED_TYPENAME range_iterator::type begin( const T& r ) { #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) using namespace range_detail; diff --git a/include/boost/range/concepts.hpp b/include/boost/range/concepts.hpp index 87c1e98..6fef2ea 100644 --- a/include/boost/range/concepts.hpp +++ b/include/boost/range/concepts.hpp @@ -252,7 +252,12 @@ namespace boost { n = i - j; } private: + // MSVC 14.1 - avoid C4596: 'difference_type': illegal qualified name in member declaration + #if defined(_MSC_VER) && _MSC_VER >= 1912 + BOOST_DEDUCED_TYPENAME difference_type n; + #else BOOST_DEDUCED_TYPENAME RandomAccessIteratorConcept::difference_type n; + #endif Iterator i; Iterator j; #endif diff --git a/include/boost/range/detail/begin.hpp b/include/boost/range/detail/begin.hpp index 1d9390f..efadaa6 100644 --- a/include/boost/range/detail/begin.hpp +++ b/include/boost/range/detail/begin.hpp @@ -32,7 +32,7 @@ namespace boost struct range_begin { template< typename C > - static BOOST_RANGE_DEDUCED_TYPENAME range_iterator::type fun( C& c ) + BOOST_CONSTEXPR static BOOST_RANGE_DEDUCED_TYPENAME range_iterator::type fun( C& c ) { return c.begin(); }; @@ -46,7 +46,7 @@ namespace boost struct range_begin { template< typename P > - static BOOST_RANGE_DEDUCED_TYPENAME range_iterator

::type fun( const P& p ) + BOOST_CONSTEXPR static BOOST_RANGE_DEDUCED_TYPENAME range_iterator

::type fun( const P& p ) { return p.first; } @@ -60,7 +60,7 @@ namespace boost struct range_begin { template - static BOOST_RANGE_DEDUCED_TYPENAME range_value::type* fun(T& t) + BOOST_CONSTEXPR static BOOST_RANGE_DEDUCED_TYPENAME range_value::type* fun(T& t) { return t; } @@ -71,7 +71,7 @@ namespace boost namespace range_adl_barrier { template< typename C > - inline BOOST_RANGE_DEDUCED_TYPENAME range_iterator::type + BOOST_CONSTEXPR inline BOOST_RANGE_DEDUCED_TYPENAME range_iterator::type begin( C& c ) { return range_detail::range_begin< BOOST_RANGE_DEDUCED_TYPENAME range_detail::range::type >::fun( c ); diff --git a/include/boost/range/detail/common.hpp b/include/boost/range/detail/common.hpp index 00b665b..2cbc554 100644 --- a/include/boost/range/detail/common.hpp +++ b/include/boost/range/detail/common.hpp @@ -18,10 +18,8 @@ #include #include #include -#include #include #include -#include #include ////////////////////////////////////////////////////////////////////////////// @@ -71,7 +69,7 @@ namespace boost BOOST_STATIC_CONSTANT( bool, is_const_wchar_t_ptr_ = sizeof( boost::range_detail::is_const_wchar_t_ptr_impl( ptr ) ) == sizeof( yes_type ) ); BOOST_STATIC_CONSTANT( bool, is_char_array_ = sizeof( boost::range_detail::is_char_array_impl( ptr ) ) == sizeof( yes_type ) ); BOOST_STATIC_CONSTANT( bool, is_wchar_t_array_ = sizeof( boost::range_detail::is_wchar_t_array_impl( ptr ) ) == sizeof( yes_type ) ); - BOOST_STATIC_CONSTANT( bool, is_string_ = (boost::mpl::or_, boost::mpl::bool_ >::value )); + BOOST_STATIC_CONSTANT( bool, is_string_ = (is_const_char_ptr_ || is_const_wchar_t_ptr_)); BOOST_STATIC_CONSTANT( bool, is_array_ = boost::is_array::value ); }; diff --git a/include/boost/range/detail/default_constructible_unary_fn.hpp b/include/boost/range/detail/default_constructible_unary_fn.hpp index 374ddda..9729e3c 100644 --- a/include/boost/range/detail/default_constructible_unary_fn.hpp +++ b/include/boost/range/detail/default_constructible_unary_fn.hpp @@ -32,6 +32,23 @@ public: : m_impl(source) { } + default_constructible_unary_fn_wrapper(const default_constructible_unary_fn_wrapper& source) + : m_impl(source.m_impl) + { + } + default_constructible_unary_fn_wrapper& operator=(const default_constructible_unary_fn_wrapper& source) + { + if (source.m_impl) + { + // Lambda are not copy/move assignable. + m_impl.emplace(*source.m_impl); + } + else + { + m_impl.reset(); + } + return *this; + } template R operator()(const Arg& arg) const { diff --git a/include/boost/range/detail/end.hpp b/include/boost/range/detail/end.hpp index f2f7178..7622921 100644 --- a/include/boost/range/detail/end.hpp +++ b/include/boost/range/detail/end.hpp @@ -33,7 +33,7 @@ namespace boost struct range_end { template< typename C > - static BOOST_RANGE_DEDUCED_TYPENAME range_iterator::type + BOOST_CONSTEXPR static BOOST_RANGE_DEDUCED_TYPENAME range_iterator::type fun( C& c ) { return c.end(); @@ -48,7 +48,7 @@ namespace boost struct range_end { template< typename P > - static BOOST_RANGE_DEDUCED_TYPENAME range_iterator

::type + BOOST_CONSTEXPR static BOOST_RANGE_DEDUCED_TYPENAME range_iterator

::type fun( const P& p ) { return p.second; @@ -63,7 +63,7 @@ namespace boost struct range_end { template - static BOOST_RANGE_DEDUCED_TYPENAME remove_extent::type* fun(T& t) + BOOST_CONSTEXPR static BOOST_RANGE_DEDUCED_TYPENAME remove_extent::type* fun(T& t) { return t + remove_extent::size; } @@ -74,7 +74,7 @@ namespace boost namespace range_adl_barrier { template< typename C > - inline BOOST_RANGE_DEDUCED_TYPENAME range_iterator::type + BOOST_CONSTEXPR inline BOOST_RANGE_DEDUCED_TYPENAME range_iterator::type end( C& c ) { return range_detail::range_end< BOOST_RANGE_DEDUCED_TYPENAME range_detail::range::type >::fun( c ); diff --git a/include/boost/range/detail/implementation_help.hpp b/include/boost/range/detail/implementation_help.hpp index f35953f..59a3ade 100644 --- a/include/boost/range/detail/implementation_help.hpp +++ b/include/boost/range/detail/implementation_help.hpp @@ -60,13 +60,13 @@ namespace boost } template< class T, std::size_t sz > - inline T* array_end( T BOOST_RANGE_ARRAY_REF()[sz] ) + BOOST_CONSTEXPR inline T* array_end( T BOOST_RANGE_ARRAY_REF()[sz] ) BOOST_NOEXCEPT { return boost_range_array + sz; } template< class T, std::size_t sz > - inline const T* array_end( const T BOOST_RANGE_ARRAY_REF()[sz] ) + BOOST_CONSTEXPR inline const T* array_end( const T BOOST_RANGE_ARRAY_REF()[sz] ) BOOST_NOEXCEPT { return boost_range_array + sz; } diff --git a/include/boost/range/detail/join_iterator.hpp b/include/boost/range/detail/join_iterator.hpp index 1020ebf..0f47f58 100644 --- a/include/boost/range/detail/join_iterator.hpp +++ b/include/boost/range/detail/join_iterator.hpp @@ -153,8 +153,12 @@ template::type >::type >::value, - typename add_const< - typename iterator_reference::type + typename add_reference< + typename add_const< + typename remove_reference< + typename iterator_reference::type + >::type + >::type >::type, typename iterator_reference::type >::type diff --git a/include/boost/range/distance.hpp b/include/boost/range/distance.hpp index 075f2d1..8dcf05b 100644 --- a/include/boost/range/distance.hpp +++ b/include/boost/range/distance.hpp @@ -15,18 +15,19 @@ # pragma once #endif +#include #include #include #include -namespace boost +namespace boost { template< class T > - inline BOOST_DEDUCED_TYPENAME range_difference::type + inline BOOST_CXX14_CONSTEXPR BOOST_DEDUCED_TYPENAME range_difference::type distance( const T& r ) { - return std::distance( boost::begin( r ), boost::end( r ) ); + return boost::distance( boost::begin( r ), boost::end( r ) ); } } // namespace 'boost' diff --git a/include/boost/range/end.hpp b/include/boost/range/end.hpp index f2a3337..588495c 100644 --- a/include/boost/range/end.hpp +++ b/include/boost/range/end.hpp @@ -37,7 +37,7 @@ namespace range_detail // primary template ////////////////////////////////////////////////////////////////////// template< typename C > - inline BOOST_DEDUCED_TYPENAME range_iterator::type + BOOST_CONSTEXPR inline BOOST_DEDUCED_TYPENAME range_iterator::type range_end( C& c ) { // @@ -53,13 +53,13 @@ namespace range_detail ////////////////////////////////////////////////////////////////////// template< typename Iterator > - inline Iterator range_end( const std::pair& p ) + BOOST_CONSTEXPR inline Iterator range_end( const std::pair& p ) { return p.second; } template< typename Iterator > - inline Iterator range_end( std::pair& p ) + BOOST_CONSTEXPR inline Iterator range_end( std::pair& p ) { return p.second; } @@ -69,13 +69,13 @@ namespace range_detail ////////////////////////////////////////////////////////////////////// template< typename T, std::size_t sz > - inline const T* range_end( const T (&a)[sz] ) + BOOST_CONSTEXPR inline const T* range_end( const T (&a)[sz] ) BOOST_NOEXCEPT { return range_detail::array_end( a ); } template< typename T, std::size_t sz > - inline T* range_end( T (&a)[sz] ) + BOOST_CONSTEXPR inline T* range_end( T (&a)[sz] ) BOOST_NOEXCEPT { return range_detail::array_end( a ); } @@ -88,7 +88,7 @@ namespace range_adl_barrier { template< class T > -inline BOOST_DEDUCED_TYPENAME range_iterator::type end( T& r ) +BOOST_CONSTEXPR inline BOOST_DEDUCED_TYPENAME range_iterator::type end( T& r ) { #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) using namespace range_detail; @@ -97,7 +97,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator::type end( T& r ) } template< class T > -inline BOOST_DEDUCED_TYPENAME range_iterator::type end( const T& r ) +BOOST_CONSTEXPR inline BOOST_DEDUCED_TYPENAME range_iterator::type end( const T& r ) { #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) using namespace range_detail; @@ -115,7 +115,7 @@ namespace boost namespace range_adl_barrier { template< class T > - inline BOOST_DEDUCED_TYPENAME range_iterator::type + BOOST_CONSTEXPR inline BOOST_DEDUCED_TYPENAME range_iterator::type const_end( const T& r ) { return boost::range_adl_barrier::end( r ); diff --git a/include/boost/range/has_range_iterator.hpp b/include/boost/range/has_range_iterator.hpp index 9eb58b3..88d8664 100644 --- a/include/boost/range/has_range_iterator.hpp +++ b/include/boost/range/has_range_iterator.hpp @@ -37,9 +37,9 @@ namespace boost T, BOOST_DEDUCED_TYPENAME ::boost::enable_if< BOOST_DEDUCED_TYPENAME mpl::eval_if, - has_type::type> >, - has_type > + has_type > >::type >::type > @@ -57,7 +57,7 @@ namespace boost struct has_range_const_iterator_impl< T, BOOST_DEDUCED_TYPENAME ::boost::enable_if< - has_type > + has_type > >::type > : boost::mpl::true_ diff --git a/include/boost/range/irange.hpp b/include/boost/range/irange.hpp index b1a1240..7d5fee5 100644 --- a/include/boost/range/irange.hpp +++ b/include/boost/range/irange.hpp @@ -217,7 +217,7 @@ namespace boost { BOOST_ASSERT( step_size != 0 ); BOOST_ASSERT( (step_size > 0) ? (last >= first) : (last <= first) ); - + typedef typename range_detail::integer_iterator_with_step iterator_t; const std::ptrdiff_t sz = static_cast(step_size >= 0 ? step_size : -step_size); @@ -225,12 +225,19 @@ namespace boost const Integer f = step_size >= 0 ? first : last; const std::ptrdiff_t num_steps = (l - f) / sz + ((l - f) % sz ? 1 : 0); BOOST_ASSERT(num_steps >= 0); - + return strided_integer_range( iterator_t(first, 0, step_size), iterator_t(first, num_steps, step_size)); } + template + integer_range + irange(Integer last) + { + return integer_range(static_cast(0), last); + } + } // namespace boost #endif // include guard diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e824ae9..b195926 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -59,6 +59,8 @@ test-suite range : [ range-test adaptor_test/indexed ] [ range-test adaptor_test/indirected ] [ range-test adaptor_test/map ] + [ range-test adaptor_test/ref_unwrapped ] + [ range-test adaptor_test/ref_unwrapped_example ] [ range-test adaptor_test/replaced ] [ range-test adaptor_test/replaced_if ] [ range-test adaptor_test/reversed ] diff --git a/test/adaptor_test/filtered.cpp b/test/adaptor_test/filtered.cpp index 17a457f..be34872 100644 --- a/test/adaptor_test/filtered.cpp +++ b/test/adaptor_test/filtered.cpp @@ -51,6 +51,23 @@ namespace boost bool operator()( IntegerT x ) const { return x % 2 != 0; } }; + struct lambda_init + { + }; + + struct lambda + { + lambda(const lambda_init& init) {} + lambda(const lambda& rhs) {} + + template< class T1 > + bool operator()(T1) const { return false; } + + private: + lambda() {} + lambda& operator=(const lambda& rhs) { return *this; } + }; + template< class Container, class Pred > void filtered_test_impl( Container& c, Pred pred ) { @@ -86,32 +103,53 @@ namespace boost test_result2.end() ); } + template< class Rng > + void check_copy_assign(Rng r) + { + Rng r2 = r; + r2 = r; + } + template< class Container, class Pred > + void filtered_range_copy_assign(Container& c, Pred pred) + { + using namespace boost::adaptors; + check_copy_assign(c | filtered(pred)); + check_copy_assign(adaptors::filter(c, pred)); + } + + template< class Container, class Pred, class PredInit > void filtered_test_impl() { using namespace boost::assign; Container c; + PredInit init; + Pred pred(init); // test empty container - filtered_test_impl(c, Pred()); + filtered_test_impl(c, pred); // test one element c += 1; - filtered_test_impl(c, Pred()); + filtered_test_impl(c, pred); // test many elements c += 1,2,2,2,3,4,4,4,4,5,6,7,8,9,9; - filtered_test_impl(c, Pred()); + filtered_test_impl(c, pred); + + // test the range and iterator are copy assignable + filtered_range_copy_assign(c, pred); } template< class Container > void filtered_test_all_predicates() { - filtered_test_impl< Container, always_false_pred >(); - filtered_test_impl< Container, always_true_pred >(); - filtered_test_impl< Container, is_odd >(); - filtered_test_impl< Container, is_even >(); + filtered_test_impl< Container, always_false_pred, always_false_pred >(); + filtered_test_impl< Container, always_true_pred, always_true_pred >(); + filtered_test_impl< Container, is_odd, is_odd >(); + filtered_test_impl< Container, is_even, is_even >(); + filtered_test_impl< Container, lambda, lambda_init >(); } void ticket_10988_single_pass() diff --git a/test/adaptor_test/ref_unwrapped.cpp b/test/adaptor_test/ref_unwrapped.cpp new file mode 100644 index 0000000..ea190b3 --- /dev/null +++ b/test/adaptor_test/ref_unwrapped.cpp @@ -0,0 +1,101 @@ +// Boost.Range library +// +// Copyright Robin Eckert 2015. 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/ +// +#include + +#define BOOST_TEST_MAIN + +#include +#include + +#include + +#if !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && !defined(BOOST_NO_CXX11_RANGE_BASED_FOR) + +namespace boost +{ + + BOOST_AUTO_TEST_CASE(test_mutable) + { + int one = 1; + int two = 2; + int three = 3; + + std::vector> input_values{one, two, three}; + + const std::vector expected{&one, &two, &three}; + std::vector actual; + + for (auto&& value : input_values | adaptors::ref_unwrapped) + { + actual.push_back(&value); + } + + BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), + expected.end(), + actual.begin(), + actual.end()); + } + + BOOST_AUTO_TEST_CASE(test_const_range) + { + int one = 1; + int two = 2; + int three = 3; + + const std::vector> input_values{one, two, three}; + + const std::vector expected{&one, &two, &three}; + std::vector actual; + + for (auto&& value : input_values | adaptors::ref_unwrapped) + { + actual.push_back(&value); + } + + BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), + expected.end(), + actual.begin(), + actual.end()); + } + + BOOST_AUTO_TEST_CASE(test_const_reference) + { + const int one = 1; + const int two = 2; + const int three = 3; + + const std::vector> input_values{one, two, three}; + + const std::vector expected{&one, &two, &three}; + std::vector actual; + + for (auto&& value : input_values | adaptors::ref_unwrapped) + { + actual.push_back(&value); + } + + BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), + expected.end(), + actual.begin(), + actual.end()); + } + + +} + +#else + +BOOST_AUTO_TEST_CASE(empty) +{ + // C++11 only +} + +#endif diff --git a/test/adaptor_test/ref_unwrapped_example.cpp b/test/adaptor_test/ref_unwrapped_example.cpp new file mode 100644 index 0000000..ab3e401 --- /dev/null +++ b/test/adaptor_test/ref_unwrapped_example.cpp @@ -0,0 +1,47 @@ +// Boost.Range library +// +// Copyright Robin Eckert 2015. 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/ +// +//[ref_unwrapped_example +#include +#include +#include + +struct example +{ + int value; +}; + +int main(int argc, const char* argv[]) +{ +//<- +#if !defined(BOOST_NO_CXX11_DECLTYPE) \ + && !defined(BOOST_NO_CXX11_RANGE_BASED_FOR) \ + && !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) \ + && !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) +//-> + using boost::adaptors::ref_unwrapped; + + example one{1}; + example two{2}; + example three{3}; + + std::vector > input{one, two, three}; + + for (auto&& entry : input | ref_unwrapped) + { + std::cout << entry.value; + } + + return 0; +//<- +#endif +//-> +} +//] diff --git a/test/adaptor_test/strided.cpp b/test/adaptor_test/strided.cpp index 6c8475d..46c16fa 100644 --- a/test/adaptor_test/strided.cpp +++ b/test/adaptor_test/strided.cpp @@ -9,7 +9,7 @@ // For more information, see http://www.boost.org/libs/range/ // // The strided_defect_Trac5014 test case is a modified version of a test case -// contributed by Michel Morin as part of the trac ticket. +// contributed by Maxim Yanchenko as part of the trac ticket. // // The deque test case has been removed due to erroneous standard library // implementations causing test failures. diff --git a/test/adaptor_test/transformed.cpp b/test/adaptor_test/transformed.cpp index adadafc..10f6a0c 100644 --- a/test/adaptor_test/transformed.cpp +++ b/test/adaptor_test/transformed.cpp @@ -38,6 +38,24 @@ namespace boost int operator()(int x) const { return x / 2; } }; + struct lambda_init + { + }; + + struct lambda + { + typedef int result_type; + + lambda(const lambda_init& init) {} + lambda(const lambda& rhs) {} + + int operator()(int x) const { return x + 1; } + + private: + lambda() {} + lambda& operator=(const lambda& rhs) { return *this; } + }; + template< class Container, class TransformFn > void transformed_test_impl_core( Container& c, TransformFn fn ) { @@ -59,13 +77,29 @@ namespace boost test_result2.begin(), test_result2.end() ); } + template< class Rng > + void check_copy_assign(Rng r) + { + Rng r2 = r; + r2 = r; + } + template< class Container, class TransformFn > + void transformed_range_copy_assign(Container& c, TransformFn fn) + { + using namespace boost::adaptors; + check_copy_assign(c | transformed(fn)); + check_copy_assign(adaptors::transform(c, fn)); + } + + template< class Container, class TransformFn, class TransformFnInit > void transformed_test_fn_impl() { using namespace boost::assign; Container c; - TransformFn fn; + TransformFnInit init; + TransformFn fn( init ); // Test empty transformed_test_impl_core(c, fn); @@ -77,13 +111,17 @@ namespace boost // Test many elements c += 1,1,1,2,2,2,2,2,3,4,5,6,7,8,9; transformed_test_impl_core(c, fn); + + // test the range and iterator are copy assignable + transformed_range_copy_assign(c, fn); } template< class Container > void transformed_test_impl() { - transformed_test_fn_impl< Container, double_x >(); - transformed_test_fn_impl< Container, halve_x >(); + transformed_test_fn_impl< Container, double_x, double_x >(); + transformed_test_fn_impl< Container, halve_x, halve_x >(); + transformed_test_fn_impl< Container, lambda, lambda_init >(); } void transformed_test() diff --git a/test/irange.cpp b/test/irange.cpp index 659401b..7e1a564 100644 --- a/test/irange.cpp +++ b/test/irange.cpp @@ -18,6 +18,23 @@ namespace boost { + // Test an integer range with a step size of 1. + template + void test_irange_impl(Integer last) + { + std::vector reference; + for (Integer i = static_cast(0); i < last; ++i) + { + reference.push_back(i); + } + + std::vector test; + boost::push_back(test, boost::irange(last)); + + BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(), + reference.begin(), reference.end() ); + } + // Test an integer range with a step size of 1. template void test_irange_impl(Integer first, Integer last) @@ -34,36 +51,52 @@ namespace boost BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(), reference.begin(), reference.end() ); } - + // Test an integer range with a runtime specified step size. template void test_irange_impl(IntegerInput first, IntegerInput last, int step) { BOOST_ASSERT( step != 0 ); - + // Skip tests that have negative values if the type is // unsigned if ((static_cast(static_cast(first)) != first) || (static_cast(static_cast(last)) != last)) return; - + std::vector reference; const std::ptrdiff_t first_p = static_cast(first); const std::ptrdiff_t last_p = static_cast(last); const std::ptrdiff_t step_p = static_cast(step); - for (std::ptrdiff_t current_value = first_p; + for (std::ptrdiff_t current_value = first_p; step_p >= 0 ? current_value < last_p : current_value > last_p; current_value += step_p) reference.push_back(current_value); std::vector test; boost::push_back(test, boost::irange(first, last, step)); - + BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(), reference.begin(), reference.end() ); } + // Test driver function that for an integer range [first, last) + // drives the test implementation through various integer + // types. + void test_irange(int last) + { + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + } + + // Test driver function that for an integer range [first, last) // drives the test implementation through various integer // types. @@ -102,6 +135,11 @@ namespace boost // number of implementation branches. void irange_unit_test() { + // Test the single-step version of irange(last) + test_irange(0); + test_irange(1); + test_irange(10); + // Test the single-step version of irange(first, last) test_irange(0, 0); test_irange(0, 1); @@ -124,14 +162,14 @@ namespace boost test_irange(9, -9, -2); test_irange(10, 20, 5); test_irange(20, 10, -5); - + test_irange(0, 0, 3); test_irange(0, 1, 3); test_irange(0, 2, 3); test_irange(0, 3, 3); test_irange(0, 4, 3); test_irange(0, 10, 3); - + test_irange(0, 0, -3); test_irange(0, -1, -3); test_irange(0, -2, -3); diff --git a/test/join.cpp b/test/join.cpp index 586f05c..300028b 100644 --- a/test/join.cpp +++ b/test/join.cpp @@ -277,6 +277,7 @@ namespace boost std::vector v2; std::vector joined; boost::push_back(joined, join(v1, v2)); + boost::push_back(joined, join(v2, v1)); } namespace trac7376 diff --git a/test/ticket_5486.cpp b/test/ticket_5486.cpp index 3a6bf4b..94d8dd4 100644 --- a/test/ticket_5486.cpp +++ b/test/ticket_5486.cpp @@ -14,7 +14,6 @@ #include #include -#include #include namespace boost @@ -22,9 +21,12 @@ namespace boost namespace { class TestTicket5486Pred - : public std::binary_function { public: + typedef int first_argument_type; + typedef int second_argument_type; + typedef bool result_type; + explicit TestTicket5486Pred(int x) {} bool operator()(int,int) const { return true; } private: