diff --git a/include/boost/range/adaptor/define_adaptor.hpp b/include/boost/range/adaptor/define_adaptor.hpp index d68c64e..26f4016 100644 --- a/include/boost/range/adaptor/define_adaptor.hpp +++ b/include/boost/range/adaptor/define_adaptor.hpp @@ -1,3 +1,13 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. 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_DEFINE_ADAPTOR_HPP_INCLUDED #define BOOST_RANGE_DEFINE_ADAPTOR_HPP_INCLUDED diff --git a/include/boost/range/adaptor/sliced.hpp b/include/boost/range/adaptor/sliced.hpp index 03c6894..7772bb5 100755 --- a/include/boost/range/adaptor/sliced.hpp +++ b/include/boost/range/adaptor/sliced.hpp @@ -27,53 +27,53 @@ namespace boost std::size_t u; }; - template< class RandomAccessRange > - class sliced_range : public boost::iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > - { - typedef boost::iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > base_t; - public: - template - sliced_range(Rng& rng, T t, U u) - : base_t(boost::make_iterator_range(rng, t, u - boost::size(rng))) - { - } - }; + template< class RandomAccessRange > + class sliced_range : public boost::iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > + { + typedef boost::iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > base_t; + public: + template + sliced_range(Rng& rng, T t, U u) + : base_t(boost::make_iterator_range(rng, t, u - boost::size(rng))) + { + } + }; - template< class RandomAccessRange > - inline sliced_range - slice( RandomAccessRange& rng, std::size_t t, std::size_t u ) - { - BOOST_ASSERT( t <= u && "error in slice indices" ); + template< class RandomAccessRange > + inline sliced_range + slice( RandomAccessRange& rng, std::size_t t, std::size_t u ) + { + BOOST_ASSERT( t <= u && "error in slice indices" ); BOOST_ASSERT( static_cast(boost::size(rng)) >= u && - "second slice index out of bounds" ); + "second slice index out of bounds" ); - return sliced_range(rng, t, u); - } + return sliced_range(rng, t, u); + } - template< class RandomAccessRange > - inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > - slice( const RandomAccessRange& rng, std::size_t t, std::size_t u ) - { - BOOST_ASSERT( t <= u && "error in slice indices" ); - BOOST_ASSERT( static_cast(boost::size(rng)) >= u && - "second slice index out of bounds" ); + template< class RandomAccessRange > + inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > + slice( const RandomAccessRange& rng, std::size_t t, std::size_t u ) + { + BOOST_ASSERT( t <= u && "error in slice indices" ); + BOOST_ASSERT( static_cast(boost::size(rng)) >= u && + "second slice index out of bounds" ); return sliced_range(rng, t, u); - } + } - template< class RandomAccessRange > - inline sliced_range - operator|( RandomAccessRange& r, const sliced& f ) - { - return sliced_range( r, f.t, f.u ); - } + template< class RandomAccessRange > + inline sliced_range + operator|( RandomAccessRange& r, const sliced& f ) + { + return sliced_range( r, f.t, f.u ); + } - template< class RandomAccessRange > - inline sliced_range - operator|( const RandomAccessRange& r, const sliced& f ) - { - return sliced_range( r, f.t, f.u ); - } + template< class RandomAccessRange > + inline sliced_range + operator|( const RandomAccessRange& r, const sliced& f ) + { + return sliced_range( r, f.t, f.u ); + } } // namespace adaptors } // namespace boost diff --git a/include/boost/range/adaptor/strided.hpp b/include/boost/range/adaptor/strided.hpp index 5f4c4fa..ab86e46 100755 --- a/include/boost/range/adaptor/strided.hpp +++ b/include/boost/range/adaptor/strided.hpp @@ -30,34 +30,34 @@ namespace boost friend class iterator_core_access; typedef iterator_adaptor, BaseIterator> super_t; - + public: typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::difference_type difference_type; - + strided_iterator() : m_stride() { } - + strided_iterator(const strided_iterator& other) : super_t(other), m_stride(other.m_stride) { } - + explicit strided_iterator(BaseIterator base_it, difference_type stride) : super_t(base_it), m_stride(stride) { } - + strided_iterator& operator=(const strided_iterator& other) { super_t::operator=(other); - + // Is the interoperation of the stride safe? m_stride = other.m_stride; return *this; } - + void increment() { std::advance(this->base_reference(), m_stride); } - + void decrement() { std::advance(this->base_reference(), -m_stride); } - + void advance(difference_type n) { std::advance(this->base_reference(), n * m_stride); } - + difference_type distance_to(const strided_iterator& other) const { @@ -66,11 +66,11 @@ namespace boost // Using the compiler generated copy constructor and // and assignment operator - + private: difference_type m_stride; }; - + template inline strided_iterator make_strided_iterator( @@ -89,9 +89,31 @@ namespace boost public: template< typename Difference > strided_range(Difference stride, Rng& rng) - : super_t(make_strided_iterator(boost::begin(rng), stride), - make_strided_iterator(boost::end(rng), stride)) + : super_t(make_first(rng, stride), make_last(rng, stride)) { + BOOST_ASSERT( stride >= 0 ); + } + private: + template + static iter_type make_first(Rng& rng, Difference stride) + { + return make_strided_iterator(boost::begin(rng), stride); + } + + template + static iter_type make_last(Rng& rng, Difference stride) + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type raw_iter_t; + typedef BOOST_DEDUCED_TYPENAME range_difference::type diff_t; + + if (stride > 0) + { + raw_iter_t it = boost::end(rng); + const diff_t count = boost::size(rng); + std::advance(it, -(count % stride)); + return iter_type(it, stride); + } + return make_strided_iterator(boost::end(rng), stride); } }; @@ -99,7 +121,7 @@ namespace boost class strided_holder : public holder { public: - strided_holder(Difference value) : holder(value) {} + explicit strided_holder(Difference value) : holder(value) {} }; template @@ -117,32 +139,32 @@ namespace boost } } // namespace range_detail - + using range_detail::strided_range; namespace adaptors { - + namespace { const range_detail::forwarder strided = range_detail::forwarder(); } - + template inline strided_range stride(Range& rng, Difference step) { return strided_range(step, rng); } - + template inline strided_range stride(const Range& rng, Difference step) { return strided_range(step, rng); } - + } // namespace 'adaptors' } // namespace 'boost' diff --git a/include/boost/range/adaptor/transformed.hpp b/include/boost/range/adaptor/transformed.hpp index 00297ca..21ce52a 100755 --- a/include/boost/range/adaptor/transformed.hpp +++ b/include/boost/range/adaptor/transformed.hpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace boost { @@ -21,17 +22,17 @@ namespace boost { template< class F, class R > - struct transform_range : - public boost::iterator_range< + struct transform_range : + public boost::iterator_range< boost::transform_iterator< F, - BOOST_DEDUCED_TYPENAME range_iterator::type + BOOST_DEDUCED_TYPENAME range_iterator::type > > { private: - typedef boost::iterator_range< + typedef boost::iterator_range< boost::transform_iterator< F, - BOOST_DEDUCED_TYPENAME range_iterator::type + BOOST_DEDUCED_TYPENAME range_iterator::type > > base; @@ -39,11 +40,11 @@ namespace boost public: typedef F transform_fn_type; typedef R source_range_type; - + transform_range( F f, R& r ) : base( make_transform_iterator( boost::begin(r), f ), - make_transform_iterator( boost::end(r), f ) ) - + make_transform_iterator( boost::end(r), f ) ) + { } }; @@ -53,43 +54,43 @@ namespace boost transform_holder( T r ) : holder(r) { } }; - + template< class InputRng, class UnaryFunction > - inline transform_range - operator|( InputRng& r, + inline transform_range + operator|( InputRng& r, const transform_holder& f ) { - return transform_range( f.val, r ); + return transform_range( f.val, r ); } - + template< class InputRng, class UnaryFunction > - inline transform_range - operator|( const InputRng& r, + inline transform_range + operator|( const InputRng& r, const transform_holder& f ) { - return transform_range( f.val, r ); + return transform_range( f.val, r ); } - + } // 'range_detail' using range_detail::transform_range; - + namespace adaptors - { + { namespace { - const range_detail::forwarder - transformed = + const range_detail::forwarder + transformed = range_detail::forwarder(); } - + template inline transform_range transform(InputRange& rng, UnaryFunction fn) { return transform_range(fn, rng); } - + template inline transform_range transform(const InputRange& rng, UnaryFunction fn) @@ -97,7 +98,7 @@ namespace boost return transform_range(fn, rng); } } // 'adaptors' - + } #endif diff --git a/include/boost/range/adaptor/type_erased.hpp b/include/boost/range/adaptor/type_erased.hpp new file mode 100644 index 0000000..85bff73 --- /dev/null +++ b/include/boost/range/adaptor/type_erased.hpp @@ -0,0 +1,90 @@ +// Boost.Range library +// +// 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_TYPE_ERASED_HPP_INCLUDED +#define BOOST_RANGE_ADAPTOR_TYPE_ERASED_HPP_INCLUDED + +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + template< + class Value, + class CategoryOrTraversal, + class Reference, + class Difference + > + class any_range + : public iterator_range< + IteratorTypeErasure::any_iterator< + Value, CategoryOrTraversal, Reference, Difference> > + { + typedef typename IteratorTypeErasure::any_iterator< + Value, CategoryOrTraversal, Reference, Difference> iterator_t; + + typedef iterator_range base_t; + public: + template + explicit any_range(Range& r) : base_t(r) {} + + template + explicit any_range(const Range& r) : base_t(r) {} + }; + + template + class any_range_generator + { + public: + typedef any_range< + BOOST_DEDUCED_TYPENAME range_value::type, + BOOST_DEDUCED_TYPENAME iterator_traversal< + BOOST_DEDUCED_TYPENAME range_iterator::type + >::type, + BOOST_DEDUCED_TYPENAME range_reference::type, + BOOST_DEDUCED_TYPENAME range_difference::type + > type; + }; + + class type_erased_tag {}; + + + } // namespace range_detail + + using range_detail::any_range; + + namespace adaptors + { + namespace + { + const range_detail::type_erased_tag type_erased = range_detail::type_erased_tag(); + } + + template + typename range_detail::any_range_generator::type + operator|(SinglePassRange& rng, range_detail::type_erased_tag) + { + typedef typename range_detail::any_range_generator::type range_t; + return range_t(rng); + } + + template + typename range_detail::any_range_generator::type + operator|(const SinglePassRange& rng, range_detail::type_erased_tag) + { + typedef typename range_detail::any_range_generator::type range_t; + return range_t(rng); + } + } +} // namespace boost + +#endif // include guard diff --git a/include/boost/range/algorithm/search_n.hpp b/include/boost/range/algorithm/search_n.hpp index b69bc6d..c277aea 100755 --- a/include/boost/range/algorithm/search_n.hpp +++ b/include/boost/range/algorithm/search_n.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include namespace boost @@ -22,6 +23,218 @@ namespace boost namespace range { +namespace range_detail +{ + // Rationale: search_n is implemented rather than delegate to + // the standard library implementation because some standard + // library implementations are broken eg. MSVC. + + // search_n forward iterator version + template + inline ForwardIterator + search_n_impl(ForwardIterator first, ForwardIterator last, Integer count, + const Value& value, std::forward_iterator_tag) + { + first = std::find(first, last, value); + while (first != last) + { + typename std::iterator_traits::difference_type n = count; + ForwardIterator i = first; + ++i; + while (i != last && n != 1 && *i==value) + { + ++i; + --n; + } + if (n == 1) + return first; + if (i == last) + return last; + first = std::find(++i, last, value); + } + return last; + } + + // search_n random-access iterator version + template + inline RandomAccessIterator + search_n_impl(RandomAccessIterator first, RandomAccessIterator last, + Integer count, const Value& value, + std::random_access_iterator_tag) + { + typedef typename std::iterator_traits::difference_type difference_t; + + difference_t tail_size = last - first; + const difference_t pattern_size = count; + + if (tail_size < pattern_size) + return last; + + const difference_t skip_offset = pattern_size - 1; + RandomAccessIterator look_ahead = first + skip_offset; + tail_size -= pattern_size; + + while (1) + { + // look_ahead here is pointing to the last element of the + // next possible match + while (!(*look_ahead == value)) // skip loop... + { + if (tail_size < pattern_size) + return last; // no match + look_ahead += pattern_size; + tail_size -= pattern_size; + } + difference_t remainder = skip_offset; + for (RandomAccessIterator back_track = look_ahead - 1; + *back_track == value; --back_track) + { + if (--remainder == 0) + { + return look_ahead - skip_offset; // matched + } + } + if (remainder > tail_size) + return last; // no match + look_ahead += remainder; + tail_size -= remainder; + } + + return last; + } + + // search_n for forward iterators using a binary predicate + // to determine a match + template + inline ForwardIterator + search_n_impl(ForwardIterator first, ForwardIterator last, + Integer count, const Value& value, + BinaryPredicate pred, std::forward_iterator_tag) + { + typedef typename std::iterator_traits::difference_type difference_t; + + while (first != last && !static_cast(pred(*first, value))) + ++first; + + while (first != last) + { + difference_t n = count; + ForwardIterator i = first; + ++i; + while (i != last && n != 1 && static_cast(pred(*i, value))) + { + ++i; + --n; + } + if (n == 1) + return first; + if (i == last) + return last; + first = ++i; + while (first != last && !static_cast(pred(*first, value))) + ++first; + } + return last; + } + + // search_n for random-access iterators using a binary predicate + // to determine a match + template + inline RandomAccessIterator + search_n_impl(RandomAccessIterator first, RandomAccessIterator last, + Integer count, const Value& value, + BinaryPredicate pred, std::random_access_iterator_tag) + { + typedef typename std::iterator_traits::difference_type difference_t; + + difference_t tail_size = last - first; + const difference_t pattern_size = count; + + if (tail_size < pattern_size) + return last; + + const difference_t skip_offset = pattern_size - 1; + RandomAccessIterator look_ahead = first + skip_offset; + tail_size -= pattern_size; + + while (1) + { + // look_ahead points to the last element of the next + // possible match + while (!static_cast(pred(*look_ahead, value))) // skip loop + { + if (tail_size < pattern_size) + return last; // no match + look_ahead += pattern_size; + tail_size -= pattern_size; + } + difference_t remainder = skip_offset; + for (RandomAccessIterator back_track = look_ahead - 1; + pred(*back_track, value); --back_track) + { + if (--remainder == 0) + return look_ahead -= skip_offset; // success + } + if (remainder > tail_size) + { + return last; // no match + } + look_ahead += remainder; + tail_size -= remainder; + } + } + + template + inline ForwardIterator + search_n_impl(ForwardIterator first, ForwardIterator last, + Integer count, const Value& value) + { + BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept)); + BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept)); + BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept::value_type>)); + //BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept2::value_type, Value>)); + + typedef typename std::iterator_traits::iterator_category cat_t; + + if (count <= 0) + return first; + if (count == 1) + return std::find(first, last, value); + return range_detail::search_n_impl(first, last, count, value, cat_t()); + } + + template + inline ForwardIterator + search_n_impl(ForwardIterator first, ForwardIterator last, + Integer count, const Value& value, + BinaryPredicate pred) + { + BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept)); + BOOST_RANGE_CONCEPT_ASSERT(( + BinaryPredicateConcept< + BinaryPredicate, + typename std::iterator_traits::value_type, + Value> + )); + + typedef typename std::iterator_traits::iterator_category cat_t; + + if (count <= 0) + return first; + if (count == 1) + { + while (first != last && !static_cast(pred(*first, value))) + ++first; + return first; + } + return range_detail::search_n_impl(first, last, count, + value, pred, cat_t()); + } +} // namespace range_detail + /// \brief template function search /// /// range-based version of the search std algorithm @@ -36,7 +249,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator::type search_n(ForwardRange& rng, Integer count, const Value& value) { BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - return std::search_n(boost::begin(rng),boost::end(rng), count, value); + return range_detail::search_n_impl(boost::begin(rng),boost::end(rng), count, value); } /// \overload @@ -45,7 +258,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator::type search_n(const ForwardRange& rng, Integer count, const Value& value) { BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - return std::search_n(boost::begin(rng), boost::end(rng), count, value); + return range_detail::search_n_impl(boost::begin(rng), boost::end(rng), count, value); } /// \overload @@ -58,7 +271,7 @@ search_n(ForwardRange& rng, Integer count, const Value& value, BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, const Value&>)); - return std::search_n(boost::begin(rng), boost::end(rng), + return range_detail::search_n_impl(boost::begin(rng), boost::end(rng), count, value, binary_pred); } @@ -72,7 +285,7 @@ search_n(const ForwardRange& rng, Integer count, const Value& value, BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, const Value&>)); - return std::search_n(boost::begin(rng), boost::end(rng), + return range_detail::search_n_impl(boost::begin(rng), boost::end(rng), count, value, binary_pred); } @@ -86,7 +299,7 @@ search_n(ForwardRange& rng, Integer count, const Value& value) { BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); return range_return:: - pack(std::search_n(boost::begin(rng),boost::end(rng), + pack(range_detail::search_n_impl(boost::begin(rng),boost::end(rng), count, value), rng); } @@ -99,7 +312,7 @@ search_n(const ForwardRange& rng, Integer count, const Value& value) { BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); return range_return:: - pack(std::search_n(boost::begin(rng), boost::end(rng), + pack(range_detail::search_n_impl(boost::begin(rng), boost::end(rng), count, value), rng); } @@ -116,7 +329,7 @@ search_n(ForwardRange& rng, Integer count, const Value& value, BOOST_DEDUCED_TYPENAME range_value::type, const Value&>)); return range_return:: - pack(std::search_n(boost::begin(rng), boost::end(rng), + pack(range_detail::search_n_impl(boost::begin(rng), boost::end(rng), count, value, pred), rng); } @@ -133,7 +346,7 @@ search_n(const ForwardRange& rng, Integer count, const Value& value, BOOST_DEDUCED_TYPENAME range_value::type, const Value&>)); return range_return:: - pack(std::search_n(boost::begin(rng), boost::end(rng), + pack(range_detail::search_n_impl(boost::begin(rng), boost::end(rng), count, value, pred), rng); } diff --git a/include/boost/range/algorithm/transform.hpp b/include/boost/range/algorithm/transform.hpp index 28f423d..fb03441 100755 --- a/include/boost/range/algorithm/transform.hpp +++ b/include/boost/range/algorithm/transform.hpp @@ -84,7 +84,7 @@ namespace boost { BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return range_detail::transform_impl( + return boost::range_detail::transform_impl( boost::begin(rng1), boost::end(rng1), boost::begin(rng2), boost::end(rng2), out, fun); diff --git a/include/boost/range/combine.hpp b/include/boost/range/combine.hpp index 8b1be00..999bbc3 100755 --- a/include/boost/range/combine.hpp +++ b/include/boost/range/combine.hpp @@ -1,3 +1,11 @@ +// Copyright Neil Groves 2010. 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_COMBINE_HPP #define BOOST_RANGE_COMBINE_HPP diff --git a/include/boost/range/counting_range.hpp b/include/boost/range/counting_range.hpp index bf22f7c..72733a2 100755 --- a/include/boost/range/counting_range.hpp +++ b/include/boost/range/counting_range.hpp @@ -1,13 +1,11 @@ -// Boost.Range library +// Copyright Neil Groves 2010. 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) // -// Copyright Neil Groves 2008. Use, modification and -// distribution is subject to the Boost Software Licence, 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 +// For more information, see http://www.boost.org/libs/range/ // - #ifndef BOOST_RANGE_COUNTING_RANGE_HPP_INCLUDED #define BOOST_RANGE_COUNTING_RANGE_HPP_INCLUDED diff --git a/include/boost/range/istream_range.hpp b/include/boost/range/istream_range.hpp index f0e9ef4..c3f2248 100755 --- a/include/boost/range/istream_range.hpp +++ b/include/boost/range/istream_range.hpp @@ -1,13 +1,11 @@ -// Boost.Range library +// Copyright Neil Groves 2010. 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) // -// Copyright Neil Groves 2008. Use, modification and -// distribution is subject to the Boost Software Licence, 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 +// For more information, see http://www.boost.org/libs/range/ // - #ifndef BOOST_RANGE_ISTREAM_RANGE_HPP_INCLUDED #define BOOST_RANGE_ISTREAM_RANGE_HPP_INCLUDED diff --git a/include/boost/range/iterator_range_core.hpp b/include/boost/range/iterator_range_core.hpp index f7df72a..ab1e80e 100755 --- a/include/boost/range/iterator_range_core.hpp +++ b/include/boost/range/iterator_range_core.hpp @@ -290,6 +290,20 @@ namespace boost return *--last; } + // pop_front() - added to model the SinglePassRangePrimitiveConcept + void pop_front() + { + BOOST_ASSERT( !empty() ); + ++m_Begin; + } + + // pop_back() - added to model the BidirectionalRangePrimitiveConcept + void pop_back() + { + BOOST_ASSERT( !empty() ); + --m_End; + } + reference operator[]( difference_type at ) const { BOOST_ASSERT( at >= 0 && at < size() ); diff --git a/include/boost/range/size.hpp b/include/boost/range/size.hpp old mode 100755 new mode 100644 index 311a692..2636905 --- a/include/boost/range/size.hpp +++ b/include/boost/range/size.hpp @@ -15,20 +15,55 @@ # pragma once #endif +#include #include #include #include #include -namespace boost +namespace boost { - - template< class T > - inline BOOST_DEDUCED_TYPENAME range_difference::type size( const T& r ) + namespace range_detail { - BOOST_ASSERT( (boost::end( r ) - boost::begin( r )) >= 0 && - "reachability invariant broken!" ); - return boost::end( r ) - boost::begin( r ); + template< class SinglePassRange > + inline BOOST_DEDUCED_TYPENAME range_difference::type + size_impl(const SinglePassRange& rng, boost::single_pass_traversal_tag) + { + typedef BOOST_DEDUCED_TYPENAME range_difference::type diff_t; + + // A compilation error here will often indicate that an algorithm + // is attempting to use boost::size(rng) for a range that is not a + // model of the RandomAccessRange Concept and does not have a + // member size() function. + // The solution to this issue is to add a range_calculate_size() + // function for the range type that will be found via ADL. + return static_cast(rng.size()); + } + + template< class SinglePassRange > + inline BOOST_DEDUCED_TYPENAME range_difference::type + size_impl(const SinglePassRange& rng, boost::random_access_traversal_tag) + { + BOOST_ASSERT( (boost::end(rng) - boost::begin(rng)) >= 0 && + "reachability invariant broken!" ); + return boost::end(rng) - boost::begin(rng); + } + } // namespace range_detail + + template + inline BOOST_DEDUCED_TYPENAME range_difference::type + range_calculate_size(const SinglePassRange& rng) + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iter_t; + typedef BOOST_DEDUCED_TYPENAME iterator_traversal::type traversal_tag; + return range_detail::size_impl(rng, traversal_tag()); + } + + template + inline BOOST_DEDUCED_TYPENAME range_difference::type + size(const SinglePassRange& rng) + { + return range_calculate_size(rng); } } // namespace 'boost'