[boost][range] - Update to relax preconditions for the strided adaptor, and numerous fixes to inspection report issues.

[SVN r67419]
This commit is contained in:
Neil Groves
2010-12-22 22:36:43 +00:00
parent 612cec17bb
commit d68174a51d
12 changed files with 502 additions and 113 deletions

View File

@ -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 #ifndef BOOST_RANGE_DEFINE_ADAPTOR_HPP_INCLUDED
#define BOOST_RANGE_DEFINE_ADAPTOR_HPP_INCLUDED #define BOOST_RANGE_DEFINE_ADAPTOR_HPP_INCLUDED

View File

@ -89,9 +89,31 @@ namespace boost
public: public:
template< typename Difference > template< typename Difference >
strided_range(Difference stride, Rng& rng) strided_range(Difference stride, Rng& rng)
: super_t(make_strided_iterator(boost::begin(rng), stride), : super_t(make_first(rng, stride), make_last(rng, stride))
make_strided_iterator(boost::end(rng), stride))
{ {
BOOST_ASSERT( stride >= 0 );
}
private:
template<typename Difference>
static iter_type make_first(Rng& rng, Difference stride)
{
return make_strided_iterator(boost::begin(rng), stride);
}
template<typename Difference>
static iter_type make_last(Rng& rng, Difference stride)
{
typedef BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type raw_iter_t;
typedef BOOST_DEDUCED_TYPENAME range_difference<Rng>::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<Difference> class strided_holder : public holder<Difference>
{ {
public: public:
strided_holder(Difference value) : holder<Difference>(value) {} explicit strided_holder(Difference value) : holder<Difference>(value) {}
}; };
template<class Rng, class Difference> template<class Rng, class Difference>

View File

@ -14,6 +14,7 @@
#include <boost/range/adaptor/argument_fwd.hpp> #include <boost/range/adaptor/argument_fwd.hpp>
#include <boost/range/iterator_range.hpp> #include <boost/range/iterator_range.hpp>
#include <boost/iterator/transform_iterator.hpp> #include <boost/iterator/transform_iterator.hpp>
#include <boost/utility/result_of.hpp>
namespace boost namespace boost
{ {

View File

@ -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 <boost/iterator/iterator_facade.hpp>
#include <boost/range/range_reference.hpp>
#include <boost/range/range_value.hpp>
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<iterator_t> base_t;
public:
template<class Range>
explicit any_range(Range& r) : base_t(r) {}
template<class Range>
explicit any_range(const Range& r) : base_t(r) {}
};
template<class Range>
class any_range_generator
{
public:
typedef any_range<
BOOST_DEDUCED_TYPENAME range_value<Range>::type,
BOOST_DEDUCED_TYPENAME iterator_traversal<
BOOST_DEDUCED_TYPENAME range_iterator<Range>::type
>::type,
BOOST_DEDUCED_TYPENAME range_reference<Range>::type,
BOOST_DEDUCED_TYPENAME range_difference<Range>::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<class SinglePassRange>
typename range_detail::any_range_generator<SinglePassRange>::type
operator|(SinglePassRange& rng, range_detail::type_erased_tag)
{
typedef typename range_detail::any_range_generator<SinglePassRange>::type range_t;
return range_t(rng);
}
template<class SinglePassRange>
typename range_detail::any_range_generator<const SinglePassRange>::type
operator|(const SinglePassRange& rng, range_detail::type_erased_tag)
{
typedef typename range_detail::any_range_generator<const SinglePassRange>::type range_t;
return range_t(rng);
}
}
} // namespace boost
#endif // include guard

View File

@ -15,6 +15,7 @@
#include <boost/range/concepts.hpp> #include <boost/range/concepts.hpp>
#include <boost/range/detail/range_return.hpp> #include <boost/range/detail/range_return.hpp>
#include <boost/range/value_type.hpp> #include <boost/range/value_type.hpp>
#include <iterator>
#include <algorithm> #include <algorithm>
namespace boost namespace boost
@ -22,6 +23,218 @@ namespace boost
namespace range 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<typename ForwardIterator, typename Integer, typename Value>
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<ForwardIterator>::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<typename RandomAccessIterator, typename Integer, typename Value>
inline RandomAccessIterator
search_n_impl(RandomAccessIterator first, RandomAccessIterator last,
Integer count, const Value& value,
std::random_access_iterator_tag)
{
typedef typename std::iterator_traits<RandomAccessIterator>::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<typename ForwardIterator, typename Integer, typename Value,
typename BinaryPredicate>
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<ForwardIterator>::difference_type difference_t;
while (first != last && !static_cast<bool>(pred(*first, value)))
++first;
while (first != last)
{
difference_t n = count;
ForwardIterator i = first;
++i;
while (i != last && n != 1 && static_cast<bool>(pred(*i, value)))
{
++i;
--n;
}
if (n == 1)
return first;
if (i == last)
return last;
first = ++i;
while (first != last && !static_cast<bool>(pred(*first, value)))
++first;
}
return last;
}
// search_n for random-access iterators using a binary predicate
// to determine a match
template<typename RandomAccessIterator, typename Integer,
typename Value, typename BinaryPredicate>
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<RandomAccessIterator>::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<bool>(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<typename ForwardIterator, typename Integer, typename Value>
inline ForwardIterator
search_n_impl(ForwardIterator first, ForwardIterator last,
Integer count, const Value& value)
{
BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept<ForwardIterator>));
BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept<Value>));
BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept<typename std::iterator_traits<ForwardIterator>::value_type>));
//BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept2<typename std::iterator_traits<ForwardIterator>::value_type, Value>));
typedef typename std::iterator_traits<ForwardIterator>::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<typename ForwardIterator, typename Integer, typename Value,
typename BinaryPredicate>
inline ForwardIterator
search_n_impl(ForwardIterator first, ForwardIterator last,
Integer count, const Value& value,
BinaryPredicate pred)
{
BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept<ForwardIterator>));
BOOST_RANGE_CONCEPT_ASSERT((
BinaryPredicateConcept<
BinaryPredicate,
typename std::iterator_traits<BinaryPredicate>::value_type,
Value>
));
typedef typename std::iterator_traits<ForwardIterator>::iterator_category cat_t;
if (count <= 0)
return first;
if (count == 1)
{
while (first != last && !static_cast<bool>(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 /// \brief template function search
/// ///
/// range-based version of the search std algorithm /// range-based version of the search std algorithm
@ -36,7 +249,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
search_n(ForwardRange& rng, Integer count, const Value& value) search_n(ForwardRange& rng, Integer count, const Value& value)
{ {
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>)); BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
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 /// \overload
@ -45,7 +258,7 @@ inline BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type
search_n(const ForwardRange& rng, Integer count, const Value& value) search_n(const ForwardRange& rng, Integer count, const Value& value)
{ {
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>)); BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
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 /// \overload
@ -58,7 +271,7 @@ search_n(ForwardRange& rng, Integer count, const Value& value,
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>)); BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate, BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type, const Value&>)); BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::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); count, value, binary_pred);
} }
@ -72,7 +285,7 @@ search_n(const ForwardRange& rng, Integer count, const Value& value,
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>)); BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate, BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
BOOST_DEDUCED_TYPENAME range_value<const ForwardRange>::type, const Value&>)); BOOST_DEDUCED_TYPENAME range_value<const ForwardRange>::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); count, value, binary_pred);
} }
@ -86,7 +299,7 @@ search_n(ForwardRange& rng, Integer count, const Value& value)
{ {
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>)); BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
return range_return<ForwardRange,re>:: return range_return<ForwardRange,re>::
pack(std::search_n(boost::begin(rng),boost::end(rng), pack(range_detail::search_n_impl(boost::begin(rng),boost::end(rng),
count, value), count, value),
rng); rng);
} }
@ -99,7 +312,7 @@ search_n(const ForwardRange& rng, Integer count, const Value& value)
{ {
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>)); BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
return range_return<const ForwardRange,re>:: return range_return<const ForwardRange,re>::
pack(std::search_n(boost::begin(rng), boost::end(rng), pack(range_detail::search_n_impl(boost::begin(rng), boost::end(rng),
count, value), count, value),
rng); rng);
} }
@ -116,7 +329,7 @@ search_n(ForwardRange& rng, Integer count, const Value& value,
BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type, BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type,
const Value&>)); const Value&>));
return range_return<ForwardRange,re>:: return range_return<ForwardRange,re>::
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), count, value, pred),
rng); rng);
} }
@ -133,7 +346,7 @@ search_n(const ForwardRange& rng, Integer count, const Value& value,
BOOST_DEDUCED_TYPENAME range_value<const ForwardRange>::type, BOOST_DEDUCED_TYPENAME range_value<const ForwardRange>::type,
const Value&>)); const Value&>));
return range_return<const ForwardRange,re>:: return range_return<const ForwardRange,re>::
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), count, value, pred),
rng); rng);
} }

View File

@ -84,7 +84,7 @@ namespace boost
{ {
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange1> )); BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange1> ));
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange2> )); BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange2> ));
return range_detail::transform_impl( return boost::range_detail::transform_impl(
boost::begin(rng1), boost::end(rng1), boost::begin(rng1), boost::end(rng1),
boost::begin(rng2), boost::end(rng2), boost::begin(rng2), boost::end(rng2),
out, fun); out, fun);

View File

@ -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 #ifndef BOOST_RANGE_COMBINE_HPP
#define BOOST_RANGE_COMBINE_HPP #define BOOST_RANGE_COMBINE_HPP

View File

@ -1,13 +1,11 @@
// Boost.Range library // Copyright Neil Groves 2010. Use, modification and
// // distribution is subject to the Boost Software License, Version
// 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 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt // 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 #ifndef BOOST_RANGE_COUNTING_RANGE_HPP_INCLUDED
#define BOOST_RANGE_COUNTING_RANGE_HPP_INCLUDED #define BOOST_RANGE_COUNTING_RANGE_HPP_INCLUDED

View File

@ -1,13 +1,11 @@
// Boost.Range library // Copyright Neil Groves 2010. Use, modification and
// // distribution is subject to the Boost Software License, Version
// 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 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt // 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 #ifndef BOOST_RANGE_ISTREAM_RANGE_HPP_INCLUDED
#define BOOST_RANGE_ISTREAM_RANGE_HPP_INCLUDED #define BOOST_RANGE_ISTREAM_RANGE_HPP_INCLUDED

View File

@ -290,6 +290,20 @@ namespace boost
return *--last; 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 reference operator[]( difference_type at ) const
{ {
BOOST_ASSERT( at >= 0 && at < size() ); BOOST_ASSERT( at >= 0 && at < size() );

45
include/boost/range/size.hpp Executable file → Normal file
View File

@ -15,6 +15,7 @@
# pragma once # pragma once
#endif #endif
#include <boost/iterator/iterator_categories.hpp>
#include <boost/range/begin.hpp> #include <boost/range/begin.hpp>
#include <boost/range/end.hpp> #include <boost/range/end.hpp>
#include <boost/range/difference_type.hpp> #include <boost/range/difference_type.hpp>
@ -22,13 +23,47 @@
namespace boost namespace boost
{ {
namespace range_detail
template< class T >
inline BOOST_DEDUCED_TYPENAME range_difference<T>::type size( const T& r )
{ {
BOOST_ASSERT( (boost::end( r ) - boost::begin( r )) >= 0 && template< class SinglePassRange >
inline BOOST_DEDUCED_TYPENAME range_difference<SinglePassRange>::type
size_impl(const SinglePassRange& rng, boost::single_pass_traversal_tag)
{
typedef BOOST_DEDUCED_TYPENAME range_difference<SinglePassRange>::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<diff_t>(rng.size());
}
template< class SinglePassRange >
inline BOOST_DEDUCED_TYPENAME range_difference<SinglePassRange>::type
size_impl(const SinglePassRange& rng, boost::random_access_traversal_tag)
{
BOOST_ASSERT( (boost::end(rng) - boost::begin(rng)) >= 0 &&
"reachability invariant broken!" ); "reachability invariant broken!" );
return boost::end( r ) - boost::begin( r ); return boost::end(rng) - boost::begin(rng);
}
} // namespace range_detail
template<class SinglePassRange>
inline BOOST_DEDUCED_TYPENAME range_difference<SinglePassRange>::type
range_calculate_size(const SinglePassRange& rng)
{
typedef BOOST_DEDUCED_TYPENAME range_iterator<const SinglePassRange>::type iter_t;
typedef BOOST_DEDUCED_TYPENAME iterator_traversal<iter_t>::type traversal_tag;
return range_detail::size_impl(rng, traversal_tag());
}
template<class SinglePassRange>
inline BOOST_DEDUCED_TYPENAME range_difference<SinglePassRange>::type
size(const SinglePassRange& rng)
{
return range_calculate_size(rng);
} }
} // namespace 'boost' } // namespace 'boost'