merge branch develop

This commit is contained in:
Neil Groves
2014-03-04 13:51:43 +00:00
59 changed files with 3156 additions and 1376 deletions

View File

@ -74,6 +74,10 @@ If the `<boost/range/mfc.hpp>` is included before or after Boost.Range headers,
]
Other Boost.Range metafunctions are defined by the following. Let `Range` be any type listed above and `Ref` be the same as `range_reference<Range>::type`. `range_value<Range>::type` is the same as `remove_reference<remove_const<Ref>::type>::type`, `range_difference<Range>::type` is the same as `std::ptrdiff_t`, and `range_pointer<Range>::type` is the same as `add_pointer<remove_reference<Ref>::type>::type`. As for `const Range`, see below.
Adam Walling has provided the header `<boost/range/mfc_map.hpp>` to add support
for the map adaptor with MFC map types.
[endsect]
[section:atl_ranges ATL Ranges]

View File

@ -69,7 +69,7 @@ What should we do if we only want to copy an element `a` if it satisfies some pr
* `boost::copy_if( rng, pred, out )`
* `boost::count_if( rng, pred )`
These algorithms are only defined to maintain a one to one relationship with the standard library algorithms. This approach of adding algorithm suffers a combinatorial explosion. Inevitably many algorithms are missing `_if` variants and there is redundant development overhead for each new algorithm. The Adaptor Generator is the design solution to this problem.
These algorithms are only defined to maintain a one to one relationship with the standard library algorithms. This approach of adding algorithm suffers a combinatorial explosion. Inevitably many algorithms are missing `_if` variants and there is redundant development overhead for each new algorithm. The Adaptor Generator is the design solution to this problem. It is conceivable that some algorithms are capable of optimization by tightly coupling the filter with the algorithm. The adaptors provide a more general solution with superior separation of orthogonal concerns.
[heading Range Adaptor alternative to copy_if algorithm]
``
@ -86,10 +86,10 @@ boost::count_if( rng, pred );
``
can be expressed as
``
boost::count( rng | boost::adaptors::filtered(pred), out );
boost::size( rng | boost::adaptors::filtered(pred) );
``
What this means is that ['*no*] algorithm with the `_if` suffix is needed. Furthermore, it turns out that algorithms with the `_copy` suffix are not needed either. Consider the somewhat misdesigned `replace_copy_if()` which may be used as
What this means is that many algorithms no longer require nor benefit from an optimized implementation with an `_if` suffix. Furthermore, it turns out that algorithms with the `_copy` suffix are often not needed either. Consider `replace_copy_if()` which may be used as
``
std::vector<int> vec;
@ -116,7 +116,7 @@ boost::push_back(vec, rng | boost::adaptors::replaced_if(pred, new_value)
In this manner, the ['*composition*] of Range Adaptors has the following consequences:
1. we no longer need `_if`, `_copy`, `_copy_if` and `_n` variants of algorithms.
1. we no longer need many of the `_if`, `_copy`, `_copy_if` and `_n` variants of algorithms.
2. we can generate a multitude of new algorithms on the fly, for example, above we generated `reverse_replace_copy_if()`

View File

@ -14,8 +14,8 @@
* [*Precondition:] The `value_type` of the range is convertible to both argument types of `bi_pred`.
* [*Postcondition:] For all adjacent elements `[x,y]` in the returned range, `bi_pred(x,y)` is `true`.
* [*Throws:] Whatever the copy constructor of `bi_pred` might throw.
* [*Range Category:] __single_pass_range__
* [*Return Type:] `boost::adjacent_filtered_range<typeof(rng)>`
* [*Range Category:] __forward_range__
* [*Return Type:] `boost::adjacent_filtered_range<decltype(rng), decltype(bi_pred)>`
* [*Returned Range Category:] The minimum of the range category of `rng` and __forward_range__
[section:adjacent_filtered_example adjacent_filtered example]

View File

@ -50,7 +50,7 @@ Defined in the header file `boost/range/algorithm/partition.hpp`
[heading Requirements]
* `ForwardRange` is a model of the __forward_range__ Concept.
* `ForwardRange` is a model of the __forward_range__ Concept. For C++ versions prior to C++11 the underlying std::partition requires Bidirectional Iterators, hence the requirement for older library versions is for a __bidirectional_range__.
* `UnaryPredicate` is a model of the `PredicateConcept`.
* `ForwardRange`'s value type is convertible to `UnaryPredicate`'s argument type.

View File

@ -73,6 +73,10 @@ namespace boost
typename range_difference<T>::type
distance( const T& r );
template< class T >
typename range_size<T>::type
size( const T& r );
//
// Bidirectional Range functions
//
@ -93,14 +97,6 @@ namespace boost
typename range_reverse_iterator<const T>::type
rend( const T& r );
//
// Random Access Range functions
//
template< class T >
typename range_difference<T>::type
size( const T& r );
//
// Special const Range functions
//

View File

@ -5,6 +5,17 @@
/]
[section:upgrade Upgrade version of Boost.Range]
[section:upgrade_from_1_55 Upgrade from version 1.55]
# __iterator_range__ is now implemented by implementing the member functions
`size()`, `operator[]` via inheritance of base-classes specialized by the
traversal type of the underlying iterator. This is normally requires no
alteration of code. It does mean that types that derive from iterator_range may
need to prefix `this->` to the various member functions. Additionally it has
been noted that some calling code was relying on member functions such as
`size()` being present despite the underlying iterators not being random-access
due to `iterator_reference<Iter>::type` not being a reference. The suggested
refactoring is to use `boost::size(rng)`.
[section:upgrade_from_1_49 Upgrade from version 1.49]
# __size__ now returns the type Rng::size_type if the range has size_type;

View File

@ -62,54 +62,44 @@ namespace boost
, pred_t(pred)
, m_last(last)
{
move_to_next_valid();
}
template<class OtherIter>
skip_iterator( const skip_iterator<OtherIter, pred_t, default_pass>& other )
: base_t(other.base())
, pred_t(other)
, m_last(other.m_last) {}
void move_to_next_valid()
, m_last(other.m_last)
{
iter_t& it = this->base_reference();
pred_t& bi_pred = *this;
if (it != m_last)
{
if (default_pass)
{
iter_t nxt = ::boost::next(it);
while (nxt != m_last && !bi_pred(*it, *nxt))
{
++it;
++nxt;
}
}
else
{
iter_t nxt = ::boost::next(it);
for(; nxt != m_last; ++it, ++nxt)
{
if (bi_pred(*it, *nxt))
{
break;
}
}
if (nxt == m_last)
{
it = m_last;
}
}
}
}
void increment()
{
iter_t& it = this->base_reference();
BOOST_ASSERT( it != m_last );
pred_t& bi_pred = *this;
iter_t prev = it;
++it;
move_to_next_valid();
if (it != m_last)
{
if (default_pass)
{
while (it != m_last && !bi_pred(*prev, *it))
{
++it;
++prev;
}
}
else
{
for (; it != m_last; ++it, ++prev)
{
if (bi_pred(*prev, *it))
{
break;
}
}
}
}
}
iter_t m_last;

View File

@ -34,7 +34,8 @@ namespace boost
public:
template<typename Rng, typename T, typename U>
sliced_range(Rng& rng, T t, U u)
: base_t(boost::make_iterator_range(rng, t, u - boost::size(rng)))
: base_t(boost::next(boost::begin(rng), t),
boost::next(boost::begin(rng), u))
{
}
};

View File

@ -13,7 +13,7 @@
#include <boost/range/adaptor/argument_fwd.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <iterator>
namespace boost
@ -23,59 +23,102 @@ namespace boost
// strided_iterator for wrapping a forward traversal iterator
template<class BaseIterator, class Category>
class strided_iterator
: public iterator_adaptor<
: public iterator_facade<
strided_iterator<BaseIterator, Category>
, BaseIterator
, use_default
, boost::forward_traversal_tag
, typename iterator_value<BaseIterator>::type
, forward_traversal_tag
, typename iterator_reference<BaseIterator>::type
, typename iterator_difference<BaseIterator>::type
>
{
friend class ::boost::iterator_core_access;
typedef iterator_adaptor<
typedef iterator_facade<
strided_iterator<BaseIterator, Category>
, BaseIterator
, use_default
, boost::forward_traversal_tag
, typename iterator_value<BaseIterator>::type
, forward_traversal_tag
, typename iterator_reference<BaseIterator>::type
, typename iterator_difference<BaseIterator>::type
> super_t;
public:
typedef BOOST_DEDUCED_TYPENAME std::iterator_traits<BaseIterator>::difference_type difference_type;
typedef typename super_t::difference_type difference_type;
typedef typename super_t::reference reference;
typedef BaseIterator base_iterator;
typedef std::forward_iterator_tag iterator_category;
strided_iterator()
: m_last()
: m_it()
, m_last()
, m_stride()
{
}
strided_iterator(base_iterator first, base_iterator it, base_iterator last, difference_type stride)
: super_t(it)
strided_iterator(base_iterator it,
base_iterator last,
difference_type stride)
: m_it(it)
, m_last(last)
, m_stride(stride)
{
}
template<class OtherIterator>
strided_iterator(const strided_iterator<OtherIterator, Category>& other,
BOOST_DEDUCED_TYPENAME enable_if_convertible<OtherIterator, base_iterator>::type* = 0)
: super_t(other)
strided_iterator(
const strided_iterator<OtherIterator, Category>& other,
typename enable_if_convertible<
OtherIterator,
base_iterator
>::type* = 0
)
: m_it(other.base())
, m_last(other.base_end())
, m_stride(other.get_stride())
{
}
base_iterator base_end() const { return m_last; }
difference_type get_stride() const { return m_stride; }
base_iterator base() const
{
return m_it;
}
base_iterator base_end() const
{
return m_last;
}
difference_type get_stride() const
{
return m_stride;
}
private:
void increment()
{
base_iterator& it = this->base_reference();
for (difference_type i = 0; (it != m_last) && (i < m_stride); ++i)
++it;
for (difference_type i = 0;
(m_it != m_last) && (i < m_stride); ++i)
{
++m_it;
}
}
reference dereference() const
{
return *m_it;
}
template<class OtherIterator>
bool equal(
const strided_iterator<OtherIterator, Category>& other,
typename enable_if_convertible<
OtherIterator,
base_iterator
>::type* = 0) const
{
return m_it == other.m_it;
}
base_iterator m_it;
base_iterator m_last;
difference_type m_stride;
};
@ -83,214 +126,514 @@ namespace boost
// strided_iterator for wrapping a bidirectional iterator
template<class BaseIterator>
class strided_iterator<BaseIterator, bidirectional_traversal_tag>
: public iterator_adaptor<
: public iterator_facade<
strided_iterator<BaseIterator, bidirectional_traversal_tag>
, BaseIterator
, use_default
, typename iterator_value<BaseIterator>::type
, bidirectional_traversal_tag
, typename iterator_reference<BaseIterator>::type
, typename iterator_difference<BaseIterator>::type
>
{
friend class ::boost::iterator_core_access;
typedef iterator_adaptor<
typedef iterator_facade<
strided_iterator<BaseIterator, bidirectional_traversal_tag>
, BaseIterator
, use_default
, typename iterator_value<BaseIterator>::type
, bidirectional_traversal_tag
, typename iterator_reference<BaseIterator>::type
, typename iterator_difference<BaseIterator>::type
> super_t;
public:
typedef BOOST_DEDUCED_TYPENAME std::iterator_traits<BaseIterator>::difference_type difference_type;
typedef typename super_t::difference_type difference_type;
typedef typename super_t::reference reference;
typedef BaseIterator base_iterator;
typedef typename boost::make_unsigned<difference_type>::type
size_type;
typedef std::bidirectional_iterator_tag iterator_category;
strided_iterator()
: m_first()
, m_last()
: m_it()
, m_offset()
, m_index()
, m_stride()
{
}
strided_iterator(base_iterator first, base_iterator it, base_iterator last, difference_type stride)
: super_t(it)
, m_first(first)
, m_last(last)
strided_iterator(base_iterator it,
size_type index,
difference_type stride)
: m_it(it)
, m_offset()
, m_index(index)
, m_stride(stride)
{
if (stride && ((m_index % stride) != 0))
m_index += (stride - (m_index % stride));
}
template<class OtherIterator>
strided_iterator(const strided_iterator<OtherIterator, bidirectional_traversal_tag>& other,
BOOST_DEDUCED_TYPENAME enable_if_convertible<OtherIterator, base_iterator>::type* = 0)
: super_t(other.base())
, m_first(other.base_begin())
, m_last(other.base_end())
strided_iterator(
const strided_iterator<
OtherIterator,
bidirectional_traversal_tag
>& other,
typename enable_if_convertible<
OtherIterator,
base_iterator
>::type* = 0
)
: m_it(other.base())
, m_offset(other.get_offset())
, m_index(other.get_index())
, m_stride(other.get_stride())
{
}
base_iterator base_begin() const { return m_first; }
base_iterator base_end() const { return m_last; }
difference_type get_stride() const { return m_stride; }
base_iterator base() const
{
return m_it;
}
difference_type get_offset() const
{
return m_offset;
}
size_type get_index() const
{
return m_index;
}
difference_type get_stride() const
{
return m_stride;
}
private:
void increment()
{
base_iterator& it = this->base_reference();
for (difference_type i = 0; (it != m_last) && (i < m_stride); ++i)
++it;
m_offset += m_stride;
}
void decrement()
{
base_iterator& it = this->base_reference();
for (difference_type i = 0; (it != m_first) && (i < m_stride); ++i)
--it;
m_offset -= m_stride;
}
base_iterator m_first;
base_iterator m_last;
reference dereference() const
{
update();
return *m_it;
}
void update() const
{
std::advance(m_it, m_offset);
m_index += m_offset;
m_offset = 0;
}
template<class OtherIterator>
bool equal(
const strided_iterator<
OtherIterator,
bidirectional_traversal_tag
>& other,
typename enable_if_convertible<
OtherIterator,
base_iterator
>::type* = 0) const
{
return (m_index + m_offset) ==
(other.get_index() + other.get_offset());
}
mutable base_iterator m_it;
mutable difference_type m_offset;
mutable size_type m_index;
difference_type m_stride;
};
// strided_iterator implementation for wrapping a random access iterator
template<class BaseIterator>
class strided_iterator<BaseIterator, random_access_traversal_tag>
: public iterator_adaptor<
: public iterator_facade<
strided_iterator<BaseIterator, random_access_traversal_tag>
, BaseIterator
, use_default
, typename iterator_value<BaseIterator>::type
, random_access_traversal_tag
, typename iterator_reference<BaseIterator>::type
, typename iterator_difference<BaseIterator>::type
>
{
friend class ::boost::iterator_core_access;
typedef iterator_adaptor<
typedef iterator_facade<
strided_iterator<BaseIterator, random_access_traversal_tag>
, BaseIterator
, use_default
, typename iterator_value<BaseIterator>::type
, random_access_traversal_tag
, typename iterator_reference<BaseIterator>::type
, typename iterator_difference<BaseIterator>::type
> super_t;
public:
typedef BOOST_DEDUCED_TYPENAME super_t::difference_type difference_type;
typedef typename super_t::difference_type difference_type;
typedef typename super_t::reference reference;
typedef BaseIterator base_iterator;
typedef std::random_access_iterator_tag iterator_category;
strided_iterator()
: m_first()
, m_last()
: m_it()
, m_first()
, m_index(0)
, m_stride()
{
}
strided_iterator(BaseIterator first, BaseIterator it, BaseIterator last, difference_type stride)
: super_t(it)
strided_iterator(
base_iterator first,
base_iterator it,
difference_type stride
)
: m_it(it)
, m_first(first)
, m_last(last)
, m_index(stride ? (it - first) / stride : 0)
, m_index(stride ? (it - first) : difference_type())
, m_stride(stride)
{
if (stride && ((m_index % stride) != 0))
m_index += (stride - (m_index % stride));
}
template<class OtherIterator>
strided_iterator(const strided_iterator<OtherIterator, random_access_traversal_tag>& other,
BOOST_DEDUCED_TYPENAME enable_if_convertible<OtherIterator, BaseIterator>::type* = 0)
: super_t(other.base())
strided_iterator(
const strided_iterator<
OtherIterator,
random_access_traversal_tag
>& other,
typename enable_if_convertible<
OtherIterator,
base_iterator
>::type* = 0
)
: m_it(other.base())
, m_first(other.base_begin())
, m_last(other.base_end())
, m_index(other.get_index())
, m_stride(other.get_stride())
{
}
base_iterator base_begin() const { return m_first; }
base_iterator base_end() const { return m_last; }
difference_type get_stride() const { return m_stride; }
difference_type get_index() const { return m_index; }
base_iterator base_begin() const
{
return m_first;
}
base_iterator base() const
{
return m_it;
}
difference_type get_stride() const
{
return m_stride;
}
difference_type get_index() const
{
return m_index;
}
private:
void increment()
{
m_index += m_stride;
if (m_index < (m_last - m_first))
this->base_reference() = m_first + m_index;
else
this->base_reference() = m_last;
}
void decrement()
{
m_index -= m_stride;
if (m_index >= 0)
this->base_reference() = m_first + m_index;
else
this->base_reference() = m_first;
}
void advance(difference_type offset)
{
offset *= m_stride;
m_index += offset;
if (m_index < 0)
this->base_reference() = m_first;
else if (m_index > (m_last - m_first))
this->base_reference() = m_last;
else
this->base_reference() = m_first + m_index;
m_index += (m_stride * offset);
}
// Implementation detail: only update the actual underlying iterator
// at the point of dereference. This is done so that the increment
// and decrement can overshoot the valid sequence as is required
// by striding. Since we can do all comparisons just with the index
// simply, and all dereferences must be within the valid range.
void update() const
{
m_it = m_first + m_index;
}
template<class OtherIterator>
difference_type distance_to(const strided_iterator<OtherIterator, random_access_traversal_tag>& other,
BOOST_DEDUCED_TYPENAME enable_if_convertible<OtherIterator, BaseIterator>::type* = 0) const
difference_type distance_to(
const strided_iterator<
OtherIterator,
random_access_traversal_tag
>& other,
typename enable_if_convertible<
OtherIterator, base_iterator>::type* = 0) const
{
if (other.base() >= this->base())
return (other.base() - this->base() + (m_stride - 1)) / m_stride;
return (other.base() - this->base() - (m_stride - 1)) / m_stride;
BOOST_ASSERT((other.m_index - m_index) % m_stride == difference_type());
return (other.m_index - m_index) / m_stride;
}
bool equal(const strided_iterator& other) const
template<class OtherIterator>
bool equal(
const strided_iterator<
OtherIterator,
random_access_traversal_tag
>& other,
typename enable_if_convertible<
OtherIterator, base_iterator>::type* = 0) const
{
return this->base() == other.base();
return m_index == other.m_index;
}
reference dereference() const
{
update();
return *m_it;
}
private:
mutable base_iterator m_it;
base_iterator m_first;
base_iterator m_last;
difference_type m_index;
difference_type m_stride;
};
template<class BaseIterator, class Difference> inline
strided_iterator<BaseIterator, BOOST_DEDUCED_TYPENAME iterator_traversal<BaseIterator>::type>
make_strided_iterator(BaseIterator first, BaseIterator it,
BaseIterator last, Difference stride)
template<class Rng, class Difference> inline
strided_iterator<
typename range_iterator<Rng>::type,
forward_traversal_tag
>
make_begin_strided_iterator(
Rng& rng,
Difference stride,
forward_traversal_tag)
{
BOOST_ASSERT( stride >= 0 );
typedef BOOST_DEDUCED_TYPENAME iterator_traversal<BaseIterator>::type traversal_tag;
return strided_iterator<BaseIterator, traversal_tag>(first, it, last, stride);
return strided_iterator<
typename range_iterator<Rng>::type,
forward_traversal_tag
>(boost::begin(rng), boost::end(rng), stride);
}
template< class Rng
, class Category = BOOST_DEDUCED_TYPENAME iterator_traversal<
BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type
template<class Rng, class Difference> inline
strided_iterator<
typename range_iterator<const Rng>::type,
forward_traversal_tag
>
make_begin_strided_iterator(
const Rng& rng,
Difference stride,
forward_traversal_tag)
{
return strided_iterator<
typename range_iterator<const Rng>::type,
forward_traversal_tag
>(boost::begin(rng), boost::end(rng), stride);
}
template<class Rng, class Difference> inline
strided_iterator<
typename range_iterator<Rng>::type,
forward_traversal_tag
>
make_end_strided_iterator(
Rng& rng,
Difference stride,
forward_traversal_tag)
{
return strided_iterator<
typename range_iterator<Rng>::type,
forward_traversal_tag
>(boost::end(rng), boost::end(rng), stride);
}
template<class Rng, class Difference> inline
strided_iterator<
typename range_iterator<const Rng>::type,
forward_traversal_tag
>
make_end_strided_iterator(
const Rng& rng,
Difference stride,
forward_traversal_tag)
{
return strided_iterator<
typename range_iterator<const Rng>::type,
forward_traversal_tag
>(boost::end(rng), boost::end(rng), stride);
}
template<class Rng, class Difference> inline
strided_iterator<
typename range_iterator<Rng>::type,
bidirectional_traversal_tag
>
make_begin_strided_iterator(
Rng& rng,
Difference stride,
bidirectional_traversal_tag)
{
typedef typename range_difference<Rng>::type difference_type;
return strided_iterator<
typename range_iterator<Rng>::type,
bidirectional_traversal_tag
>(boost::begin(rng), difference_type(), stride);
}
template<class Rng, class Difference> inline
strided_iterator<
typename range_iterator<const Rng>::type,
bidirectional_traversal_tag
>
make_begin_strided_iterator(
const Rng& rng,
Difference stride,
bidirectional_traversal_tag)
{
typedef typename range_difference<const Rng>::type difference_type;
return strided_iterator<
typename range_iterator<const Rng>::type,
bidirectional_traversal_tag
>(boost::begin(rng), difference_type(), stride);
}
template<class Rng, class Difference> inline
strided_iterator<
typename range_iterator<Rng>::type,
bidirectional_traversal_tag
>
make_end_strided_iterator(
Rng& rng,
Difference stride,
bidirectional_traversal_tag)
{
return strided_iterator<
typename range_iterator<Rng>::type,
bidirectional_traversal_tag
>(boost::end(rng), boost::size(rng), stride);
}
template<class Rng, class Difference> inline
strided_iterator<
typename range_iterator<const Rng>::type,
bidirectional_traversal_tag
>
make_end_strided_iterator(
const Rng& rng,
Difference stride,
bidirectional_traversal_tag)
{
return strided_iterator<
typename range_iterator<const Rng>::type,
bidirectional_traversal_tag
>(boost::end(rng), boost::size(rng), stride);
}
template<class Rng, class Difference> inline
strided_iterator<
typename range_iterator<Rng>::type,
random_access_traversal_tag
>
make_begin_strided_iterator(
Rng& rng,
Difference stride,
random_access_traversal_tag)
{
return strided_iterator<
typename range_iterator<Rng>::type,
random_access_traversal_tag
>(boost::begin(rng), boost::begin(rng), stride);
}
template<class Rng, class Difference> inline
strided_iterator<
typename range_iterator<const Rng>::type,
random_access_traversal_tag
>
make_begin_strided_iterator(
const Rng& rng,
Difference stride,
random_access_traversal_tag)
{
return strided_iterator<
typename range_iterator<const Rng>::type,
random_access_traversal_tag
>(boost::begin(rng), boost::begin(rng), stride);
}
template<class Rng, class Difference> inline
strided_iterator<
typename range_iterator<Rng>::type,
random_access_traversal_tag
>
make_end_strided_iterator(
Rng& rng,
Difference stride,
random_access_traversal_tag)
{
return strided_iterator<
typename range_iterator<Rng>::type,
random_access_traversal_tag
>(boost::begin(rng), boost::end(rng), stride);
}
template<class Rng, class Difference> inline
strided_iterator<
typename range_iterator<const Rng>::type,
random_access_traversal_tag
>
make_end_strided_iterator(
const Rng& rng,
Difference stride,
random_access_traversal_tag)
{
return strided_iterator<
typename range_iterator<const Rng>::type,
random_access_traversal_tag
>(boost::begin(rng), boost::end(rng), stride);
}
template<
class Rng,
class Category =
typename iterator_traversal<
typename range_iterator<Rng>::type
>::type
>
class strided_range
: public iterator_range<
range_detail::strided_iterator<
BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type,
typename range_iterator<Rng>::type,
Category
>
>
{
typedef range_detail::strided_iterator<
BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type,
typename range_iterator<Rng>::type,
Category
> iter_type;
typedef iterator_range<iter_type> super_t;
public:
template<class Difference>
strided_range(Difference stride, Rng& rng)
: super_t(make_strided_iterator(boost::begin(rng), boost::begin(rng), boost::end(rng), stride),
make_strided_iterator(boost::begin(rng), boost::end(rng), boost::end(rng), stride))
: super_t(
range_detail::make_begin_strided_iterator(
rng, stride,
typename iterator_traversal<
typename range_iterator<Rng>::type
>::type()),
range_detail::make_end_strided_iterator(
rng, stride,
typename iterator_traversal<
typename range_iterator<Rng>::type
>::type()))
{
BOOST_ASSERT( stride >= 0 );
}
@ -300,7 +643,10 @@ namespace boost
class strided_holder : public holder<Difference>
{
public:
explicit strided_holder(Difference value) : holder<Difference>(value) {}
explicit strided_holder(Difference value)
: holder<Difference>(value)
{
}
};
template<class Rng, class Difference>
@ -327,7 +673,8 @@ namespace boost
namespace
{
const range_detail::forwarder<range_detail::strided_holder>
strided = range_detail::forwarder<range_detail::strided_holder>();
strided = range_detail::forwarder<
range_detail::strided_holder>();
}
template<class Range, class Difference>

View File

@ -31,7 +31,7 @@ namespace boost
IteratorCategoryTag1,
IteratorCategoryTag2 )
{
while (true)
for (;;)
{
// If we have reached the end of the left range then this is
// the end of the loop. They are equal if and only if we have
@ -71,7 +71,7 @@ namespace boost
IteratorCategoryTag1,
IteratorCategoryTag2 )
{
while (true)
for (;;)
{
// If we have reached the end of the left range then this is
// the end of the loop. They are equal if and only if we have
@ -120,7 +120,9 @@ namespace boost
RandomAccessTraversalReadableIterator1 last1,
RandomAccessTraversalReadableIterator2 first2,
RandomAccessTraversalReadableIterator2 last2,
BinaryPredicate pred )
BinaryPredicate pred,
std::random_access_iterator_tag,
std::random_access_iterator_tag )
{
return ((last1 - first1) == (last2 - first2))
&& std::equal(first1, last1, first2, pred);

View File

@ -15,6 +15,7 @@
#include <boost/range/difference_type.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/detail/implementation_help.hpp>
#include <boost/assert.hpp>
namespace boost
@ -27,7 +28,7 @@ inline Container& push_back( Container& on, const Range& from )
{
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<Container> ));
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const Range> ));
BOOST_ASSERT( (void*)&on != (void*)&from &&
BOOST_ASSERT_MSG(!range_detail::is_same_object(on, from),
"cannot copy from a container to itself");
on.insert( on.end(), boost::begin(from), boost::end(from) );
return on;

View File

@ -15,6 +15,7 @@
#include <boost/range/difference_type.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/detail/implementation_help.hpp>
#include <boost/assert.hpp>
namespace boost
@ -27,7 +28,7 @@ inline Container& push_front( Container& on, const Range& from )
{
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<Container> ));
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const Range> ));
BOOST_ASSERT( (void*)&on != (void*)&from &&
BOOST_ASSERT_MSG(!range_detail::is_same_object(on, from),
"cannot copy from a container to itself");
on.insert( on.begin(), boost::begin(from), boost::end(from) );
return on;

View File

@ -17,11 +17,11 @@
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/value_type.hpp>
#include <boost/range/iterator.hpp>
#include <boost/iterator/counting_iterator.hpp>
namespace boost
{
template<class Value>
inline iterator_range<counting_iterator<Value> >
counting_range(Value first, Value last)
@ -33,29 +33,39 @@ namespace boost
}
template<class Range>
inline iterator_range<counting_iterator<BOOST_DEDUCED_TYPENAME range_value<const Range>::type> >
inline iterator_range<
counting_iterator<
BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type
>
>
counting_range(const Range& rng)
{
typedef counting_iterator<BOOST_DEDUCED_TYPENAME range_value<const Range>::type> counting_iterator_t;
typedef counting_iterator<
BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type
> counting_iterator_t;
typedef iterator_range<counting_iterator_t> result_t;
return boost::empty(rng)
? result_t()
: result_t(
counting_iterator_t(*boost::begin(rng)),
counting_iterator_t(*boost::prior(boost::end(rng))));
return result_t(counting_iterator_t(boost::begin(rng)),
counting_iterator_t(boost::end(rng)));
}
template<class Range>
inline iterator_range<counting_iterator<BOOST_DEDUCED_TYPENAME range_value<Range>::type> >
inline iterator_range<
counting_iterator<
BOOST_DEDUCED_TYPENAME range_iterator<Range>::type
>
>
counting_range(Range& rng)
{
typedef counting_iterator<BOOST_DEDUCED_TYPENAME range_value<Range>::type> counting_iterator_t;
typedef counting_iterator<
BOOST_DEDUCED_TYPENAME range_iterator<Range>::type
> counting_iterator_t;
typedef iterator_range<counting_iterator_t> result_t;
return boost::empty(rng)
? result_t()
: result_t(
counting_iterator_t(*boost::begin(rng)),
counting_iterator_t(*boost::prior(boost::end(rng))));
return result_t(counting_iterator_t(boost::begin(rng)),
counting_iterator_t(boost::end(rng)));
}
} // namespace boost

View File

@ -27,25 +27,40 @@ namespace boost
{
typedef typename mpl::if_<
typename is_reference<T>::type,
typename add_reference<
typename add_const<
typename remove_reference<T>::type
>::type
>::type,
>::type&,
T
>::type type;
};
template<class T>
struct mutable_reference_type_generator
{
typedef typename mpl::if_<
typename mpl::and_<
typename is_const<T>::type,
typename mpl::not_<typename is_reference<T>::type>::type
>::type,
T,
typename add_reference<T>::type
>::type type;
};
template<
class Reference
, class Buffer
>
struct any_incrementable_iterator_interface
{
typedef Reference reference;
typedef typename mutable_reference_type_generator<
Reference
>::type reference;
typedef typename const_reference_type_generator<
Reference
>::type const_reference;
typedef typename remove_const<
typename remove_reference<Reference>::type
>::type reference_as_value_type;
@ -87,7 +102,7 @@ namespace boost
virtual any_single_pass_iterator_interface<reference_as_value_type, Buffer>*
clone_reference_as_value(buffer_type& buffer) const = 0;
virtual Reference dereference() const = 0;
virtual reference dereference() const = 0;
virtual bool equal(const any_single_pass_iterator_interface& other) const = 0;
};

View File

@ -19,6 +19,17 @@ namespace boost
{
namespace range_detail
{
template<class Reference, class T>
Reference dereference_cast(T& x)
{
return static_cast<Reference>(x);
}
template<class Reference, class T>
Reference dereference_cast(const T& x)
{
return static_cast<Reference>(const_cast<T&>(x));
}
template<
class WrappedIterator
, class Reference
@ -114,7 +125,13 @@ namespace boost
{
struct disabler {};
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassIteratorConcept<WrappedIterator> ));
typedef any_single_pass_iterator_interface<
Reference,
Buffer
> base_type;
public:
typedef typename base_type::reference reference;
any_single_pass_iterator_wrapper()
: m_it()
@ -178,9 +195,9 @@ namespace boost
return m_it == boost::polymorphic_downcast<const any_single_pass_iterator_wrapper*>(&other)->m_it;
}
virtual Reference dereference() const
virtual reference dereference() const
{
return *m_it;
return dereference_cast<reference>(*m_it);
}
private:
@ -199,7 +216,14 @@ namespace boost
>
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardIteratorConcept<WrappedIterator> ));
typedef any_forward_iterator_interface<
Reference,
Buffer
> base_type;
public:
typedef typename base_type::reference reference;
any_forward_iterator_wrapper()
: m_it()
{}
@ -263,9 +287,9 @@ namespace boost
return m_it == boost::polymorphic_downcast<const any_forward_iterator_wrapper*>(&other)->m_it;
}
virtual Reference dereference() const
virtual reference dereference() const
{
return *m_it;
return dereference_cast<reference>(*m_it);
}
private:
WrappedIterator m_it;
@ -283,7 +307,14 @@ namespace boost
>
{
BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalIteratorConcept<WrappedIterator> ));
typedef any_bidirectional_iterator_interface<
Reference,
Buffer
> base_type;
public:
typedef typename base_type::reference reference;
any_bidirectional_iterator_wrapper()
: m_it()
{
@ -353,9 +384,9 @@ namespace boost
return m_it == boost::polymorphic_downcast<const any_bidirectional_iterator_wrapper*>(&other)->m_it;
}
virtual Reference dereference() const
virtual reference dereference() const
{
return *m_it;
return dereference_cast<reference>(*m_it);
}
private:
@ -376,7 +407,14 @@ namespace boost
>
{
BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessIteratorConcept<WrappedIterator> ));
typedef any_random_access_iterator_interface<
Reference,
Difference,
Buffer
> base_type;
public:
typedef typename base_type::reference reference;
typedef Difference difference_type;
any_random_access_iterator_wrapper()
@ -457,9 +495,9 @@ namespace boost
m_it += offset;
}
virtual Reference dereference() const
virtual reference dereference() const
{
return *m_it;
return dereference_cast<reference>(*m_it);
}
virtual Difference distance_to(const any_random_access_iterator_interface<Reference, Difference, Buffer>& other) const

View File

@ -0,0 +1,66 @@
// Boost.Range library
//
// Copyright Neil Groves 2014.
//
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
//
// For more information, see http://www.boost.org/libs/range/
//
#ifndef BOOST_RANGE_DETAIL_HAS_MEMBER_SIZE_HPP
#define BOOST_RANGE_DETAIL_HAS_MEMBER_SIZE_HPP
#include <boost/type_traits/is_class.hpp>
#include <boost/type_traits/is_member_function_pointer.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/cstdint.hpp>
namespace boost
{
namespace range_detail
{
template<class T>
class has_member_size_impl
{
private:
template<class U, U>
class check
{
};
template<class C>
static boost::uint8_t f(check<std::size_t(C::*)(void) const, &C::size>*);
template<class C>
static boost::uint16_t f(...);
public:
static const bool value =
(sizeof(f<T>(0)) == sizeof(boost::uint8_t));
typedef typename mpl::if_c<
(sizeof(f<T>(0)) == sizeof(boost::uint8_t)),
mpl::true_,
mpl::false_
>::type type;
};
template<class T>
struct has_member_size
{
typedef typename mpl::and_<
typename is_class<T>::type,
typename has_member_size_impl<const T>::type
>::type type;
static const bool value =
is_class<T>::value && has_member_size_impl<const T>::value;
};
} // namespace range_detail
}// namespace boost
#endif // include guard

View File

@ -95,6 +95,17 @@ namespace boost
return sz;
}
inline bool is_same_address(const void* l, const void* r)
{
return l == r;
}
template<class T1, class T2>
inline bool is_same_object(const T1& l, const T2& r)
{
return range_detail::is_same_address(&l, &r);
}
} // namespace 'range_detail'
} // namespace 'boost'

View File

@ -9,6 +9,9 @@
// aschoedl contributed an improvement to the determination
// of the Reference type parameter.
//
// Leonid Gershanovich reported Trac ticket 7376 about the dereference operator
// requiring identical reference types due to using the ternary if.
//
// For more information, see http://www.boost.org/libs/range/
//
#ifndef BOOST_RANGE_DETAIL_JOIN_ITERATOR_HPP_INCLUDED
@ -117,7 +120,8 @@ public:
return *m_it;
}
bool equal(const join_iterator_union& other, unsigned int selected) const
bool equal(const join_iterator_union& other,
unsigned int /*selected*/) const
{
return m_it == other.m_it;
}

View File

@ -51,6 +51,7 @@ namespace boost
typedef typename base_t::value_type value_type;
typedef typename base_t::difference_type difference_type;
typedef typename base_t::reference reference;
typedef std::random_access_iterator_tag iterator_category;
integer_iterator() : m_value() {}
explicit integer_iterator(value_type x) : m_value(x) {}
@ -73,7 +74,11 @@ namespace boost
difference_type distance_to(const integer_iterator& other) const
{
return other.m_value - m_value;
return is_signed<value_type>::value
? (other.m_value - m_value)
: (other.m_value >= m_value)
? static_cast<difference_type>(other.m_value - m_value)
: -static_cast<difference_type>(m_value - other.m_value);
}
bool equal(const integer_iterator& other) const
@ -123,6 +128,7 @@ namespace boost
typedef typename base_t::value_type value_type;
typedef typename base_t::difference_type difference_type;
typedef typename base_t::reference reference;
typedef std::random_access_iterator_tag iterator_category;
integer_iterator_with_step(value_type first, difference_type step, value_type step_size)
: m_first(first)
@ -164,7 +170,7 @@ namespace boost
friend class ::boost::iterator_core_access;
value_type m_first;
value_type m_step;
difference_type m_step;
difference_type m_step_size;
};

View File

@ -24,10 +24,13 @@
#include <boost/mpl/or.hpp>
#include <boost/type_traits/is_abstract.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/range/functions.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/difference_type.hpp>
#include <boost/range/has_range_iterator.hpp>
#include <boost/range/algorithm/equal.hpp>
#include <boost/range/detail/safe_bool.hpp>
#include <boost/utility/enable_if.hpp>
@ -77,7 +80,7 @@ namespace boost
template< class Left, class Right >
inline bool greater_than( const Left& l, const Right& r )
{
return less_than(r,l);
return iterator_range_detail::less_than(r,l);
}
template< class Left, class Right >
@ -100,8 +103,251 @@ namespace boost
return boost::equal(l, r);
}
struct range_tag { };
struct const_range_tag { };
struct range_tag
{
};
struct const_range_tag
{
};
struct iterator_range_tag
{
};
template<class IteratorT, class TraversalTag>
class iterator_range_base
: public iterator_range_tag
{
typedef range_detail::safe_bool<
IteratorT iterator_range_base<IteratorT, TraversalTag>::*
> safe_bool_t;
typedef iterator_range_base<IteratorT, TraversalTag> type;
protected:
typedef iterator_range_impl<IteratorT> impl;
public:
typedef BOOST_DEDUCED_TYPENAME
safe_bool_t::unspecified_bool_type unspecified_bool_type;
typedef BOOST_DEDUCED_TYPENAME
iterator_value<IteratorT>::type value_type;
typedef BOOST_DEDUCED_TYPENAME
iterator_difference<IteratorT>::type difference_type;
typedef std::size_t size_type; // note: must be unsigned
// Needed because value-type is the same for
// const and non-const iterators
typedef BOOST_DEDUCED_TYPENAME
iterator_reference<IteratorT>::type reference;
//! const_iterator type
/*!
There is no distinction between const_iterator and iterator.
These typedefs are provides to fulfill container interface
*/
typedef IteratorT const_iterator;
//! iterator type
typedef IteratorT iterator;
protected:
iterator_range_base()
: m_Begin()
, m_End()
{
}
template<class Iterator>
iterator_range_base(Iterator Begin, Iterator End)
: m_Begin(Begin)
, m_End(End)
{
}
public:
IteratorT begin() const
{
return m_Begin;
}
IteratorT end() const
{
return m_End;
}
bool empty() const
{
return m_Begin == m_End;
}
operator unspecified_bool_type() const
{
return safe_bool_t::to_unspecified_bool(
m_Begin != m_End, &iterator_range_base::m_Begin);
}
bool operator!() const
{
return empty();
}
bool equal(const iterator_range_base& r) const
{
return m_Begin == r.m_Begin && m_End == r.m_End;
}
reference front() const
{
BOOST_ASSERT(!empty());
return *m_Begin;
}
void pop_front()
{
BOOST_ASSERT(!empty());
++m_Begin;
}
protected:
template<class Iterator>
void assign(Iterator first, Iterator last)
{
m_Begin = first;
m_End = last;
}
template<class SinglePassRange>
void assign(const SinglePassRange& r)
{
m_Begin = impl::adl_begin(r);
m_End = impl::adl_end(r);
}
template<class SinglePassRange>
void assign(SinglePassRange& r)
{
m_Begin = impl::adl_begin(r);
m_End = impl::adl_end(r);
}
IteratorT m_Begin;
IteratorT m_End;
};
template<class IteratorT>
class iterator_range_base<IteratorT, bidirectional_traversal_tag>
: public iterator_range_base<IteratorT, forward_traversal_tag>
{
typedef iterator_range_base<IteratorT, forward_traversal_tag> base_type;
protected:
iterator_range_base()
{
}
template<class Iterator>
iterator_range_base(Iterator first, Iterator last)
: iterator_range_base<IteratorT, forward_traversal_tag>(first, last)
{
}
public:
BOOST_DEDUCED_TYPENAME base_type::reference back() const
{
BOOST_ASSERT(!this->empty());
return *boost::prior(this->m_End);
}
void pop_back()
{
BOOST_ASSERT(!this->empty());
--this->m_End;
}
};
template<class IteratorT>
class iterator_range_base<IteratorT, random_access_traversal_tag>
: public iterator_range_base<IteratorT, bidirectional_traversal_tag>
{
typedef iterator_range_base<
IteratorT, bidirectional_traversal_tag> base_type;
public:
typedef BOOST_DEDUCED_TYPENAME
boost::mpl::if_<
boost::mpl::or_<
boost::is_abstract<
BOOST_DEDUCED_TYPENAME base_type::value_type
>,
boost::is_array<
BOOST_DEDUCED_TYPENAME base_type::value_type
>
>,
BOOST_DEDUCED_TYPENAME base_type::reference,
BOOST_DEDUCED_TYPENAME base_type::value_type
>::type abstract_value_type;
// Rationale:
// typedef these here to reduce verbiage in the implementation of this
// type.
typedef BOOST_DEDUCED_TYPENAME base_type::difference_type difference_type;
typedef BOOST_DEDUCED_TYPENAME base_type::size_type size_type;
typedef BOOST_DEDUCED_TYPENAME base_type::reference reference;
protected:
iterator_range_base()
{
}
template<class Iterator>
iterator_range_base(Iterator first, Iterator last)
: iterator_range_base<IteratorT, bidirectional_traversal_tag>(
first, last)
{
}
public:
reference operator[](difference_type at) const
{
BOOST_ASSERT(at >= 0 && at < size());
return this->m_Begin[at];
}
//
// When storing transform iterators, operator[]()
// fails because it returns by reference. Therefore
// operator()() is provided for these cases.
//
abstract_value_type operator()(difference_type at) const
{
BOOST_ASSERT(at >= 0 && at < size());
return this->m_Begin[at];
}
void pop_front(difference_type n)
{
BOOST_ASSERT(n >= difference_type());
BOOST_ASSERT(size() >= static_cast<size_type>(n));
std::advance(this->m_Begin, n);
}
void pop_back(difference_type n)
{
BOOST_ASSERT(n >= difference_type());
BOOST_ASSERT(size() >= static_cast<size_type>(n));
std::advance(this->m_End, -n);
}
BOOST_DEDUCED_TYPENAME base_type::size_type size() const
{
return this->m_End - this->m_Begin;
}
};
}
// iterator range template class -----------------------------------------//
@ -125,251 +371,109 @@ namespace boost
*/
template<class IteratorT>
class iterator_range
: public iterator_range_detail::iterator_range_base<
IteratorT,
BOOST_DEDUCED_TYPENAME iterator_traversal<IteratorT>::type
>
{
typedef range_detail::safe_bool< IteratorT iterator_range<IteratorT>::* > safe_bool_t;
protected: // Used by sub_range
//! implementation class
typedef iterator_range_detail::iterator_range_base<
IteratorT,
BOOST_DEDUCED_TYPENAME iterator_traversal<IteratorT>::type
> base_type;
template<class Source>
struct is_compatible_range
: is_convertible<
BOOST_DEDUCED_TYPENAME mpl::eval_if<
has_range_iterator<Source>,
range_iterator<Source>,
mpl::identity<void>
>::type,
BOOST_DEDUCED_TYPENAME base_type::iterator
>
{
};
protected:
typedef iterator_range_detail::iterator_range_impl<IteratorT> impl;
public:
//! this type
typedef iterator_range<IteratorT> type;
typedef BOOST_DEDUCED_TYPENAME safe_bool_t::unspecified_bool_type unspecified_bool_type;
//BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(value_type);
//! Encapsulated value type
typedef BOOST_DEDUCED_TYPENAME
iterator_value<IteratorT>::type value_type;
//! Difference type
typedef BOOST_DEDUCED_TYPENAME
iterator_difference<IteratorT>::type difference_type;
//! Size type
typedef std::size_t size_type; // note: must be unsigned
//! This type
typedef iterator_range<IteratorT> this_type;
//! Reference type
//
// Needed because value-type is the same for
// const and non-const iterators
//
typedef BOOST_DEDUCED_TYPENAME
iterator_reference<IteratorT>::type reference;
//! const_iterator type
/*!
There is no distinction between const_iterator and iterator.
These typedefs are provides to fulfill container interface
*/
typedef IteratorT const_iterator;
//! iterator type
typedef IteratorT iterator;
private: // for return value of operator()()
typedef BOOST_DEDUCED_TYPENAME
boost::mpl::if_< boost::mpl::or_< boost::is_abstract< value_type >,
boost::is_array< value_type > >,
reference, value_type >::type abstract_value_type;
public:
iterator_range() : m_Begin( iterator() ), m_End( iterator() )
{ }
//! Constructor from a pair of iterators
template< class Iterator >
iterator_range( Iterator Begin, Iterator End ) :
m_Begin(Begin), m_End(End)
{}
//! Constructor from a Range
template< class Range >
iterator_range( const Range& r ) :
m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
{}
//! Constructor from a Range
template< class Range >
iterator_range( Range& r ) :
m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
{}
//! Constructor from a Range
template< class Range >
iterator_range( const Range& r, iterator_range_detail::const_range_tag ) :
m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
{}
//! Constructor from a Range
template< class Range >
iterator_range( Range& r, iterator_range_detail::range_tag ) :
m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
{}
this_type& operator=( const this_type& r )
iterator_range()
{
m_Begin = r.begin();
m_End = r.end();
}
template<class Iterator>
iterator_range(Iterator first, Iterator last)
: base_type(first, last)
{
}
template<class SinglePassRange>
iterator_range(
const SinglePassRange& r,
BOOST_DEDUCED_TYPENAME enable_if<
is_compatible_range<const SinglePassRange>
>::type* = 0
)
: base_type(impl::adl_begin(r), impl::adl_end(r))
{
}
template<class SinglePassRange>
iterator_range(
SinglePassRange& r,
BOOST_DEDUCED_TYPENAME enable_if<
is_compatible_range<SinglePassRange>
>::type* = 0
)
: base_type(impl::adl_begin(r), impl::adl_end(r))
{
}
template<class SinglePassRange>
iterator_range(const SinglePassRange& r,
iterator_range_detail::const_range_tag)
: base_type(impl::adl_begin(r), impl::adl_end(r))
{
}
template<class SinglePassRange>
iterator_range(SinglePassRange& r,
iterator_range_detail::range_tag)
: base_type(impl::adl_begin(r), impl::adl_end(r))
{
}
template<class Iterator>
iterator_range& operator=(const iterator_range<Iterator>& other)
{
this->assign(other.begin(), other.end());
return *this;
}
template<class Iterator>
iterator_range& operator=( const iterator_range<Iterator>& r )
iterator_range& operator=(iterator_range<Iterator>& other)
{
m_Begin = r.begin();
m_End = r.end();
this->assign(other.begin(), other.end());
return *this;
}
template< class ForwardRange >
iterator_range& operator=( ForwardRange& r )
template<class SinglePassRange>
iterator_range& operator=(SinglePassRange& r)
{
m_Begin = impl::adl_begin( r );
m_End = impl::adl_end( r );
this->assign(r);
return *this;
}
template< class ForwardRange >
iterator_range& operator=( const ForwardRange& r )
template<class SinglePassRange>
iterator_range& operator=(const SinglePassRange& r)
{
m_Begin = impl::adl_begin( r );
m_End = impl::adl_end( r );
this->assign(r);
return *this;
}
IteratorT begin() const
{
return m_Begin;
}
IteratorT end() const
{
return m_End;
}
difference_type size() const
{
return m_End - m_Begin;
}
bool empty() const
{
return m_Begin == m_End;
}
operator unspecified_bool_type() const
{
return safe_bool_t::to_unspecified_bool(m_Begin != m_End, &iterator_range::m_Begin);
}
bool operator!() const
{
return empty();
}
bool equal( const iterator_range& r ) const
{
return m_Begin == r.m_Begin && m_End == r.m_End;
}
#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
bool operator==( const iterator_range& r ) const
{
return boost::equal( *this, r );
}
bool operator!=( const iterator_range& r ) const
{
return !operator==(r);
}
bool operator<( const iterator_range& r ) const
{
return iterator_range_detail::less_than( *this, r );
}
bool operator>( const iterator_range& r ) const
{
return iterator_range_detail::greater_than( *this, r );
}
bool operator<=( const iterator_range& r ) const
{
return iterator_range_detail::less_or_equal_than( *this, r );
}
bool operator>=( const iterator_range& r ) const
{
return iterator_range_detail::greater_or_equal_than( *this, r );
}
#endif
public: // convenience
reference front() const
{
BOOST_ASSERT( !empty() );
return *m_Begin;
}
reference back() const
{
BOOST_ASSERT( !empty() );
IteratorT last( m_End );
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() );
return m_Begin[at];
}
//
// When storing transform iterators, operator[]()
// fails because it returns by reference. Therefore
// operator()() is provided for these cases.
//
abstract_value_type operator()( difference_type at ) const
{
BOOST_ASSERT( at >= 0 && at < size() );
return m_Begin[at];
}
iterator_range& advance_begin( difference_type n )
{
std::advance( m_Begin, n );
return *this;
}
iterator_range& advance_end( difference_type n )
{
std::advance( m_End, n );
return *this;
}
private:
// begin and end iterators
IteratorT m_Begin;
IteratorT m_End;
protected:
//
// Allow subclasses an easy way to access the
@ -383,139 +487,144 @@ namespace boost
/////////////////////////////////////////////////////////////////////
// comparison operators
/////////////////////////////////////////////////////////////////////
template< class IteratorT, class ForwardRange >
inline bool operator==( const ForwardRange& l,
const iterator_range<IteratorT>& r )
template<class SinglePassRange1, class SinglePassRange2>
inline BOOST_DEDUCED_TYPENAME enable_if<
mpl::or_<
is_convertible<
const SinglePassRange1&,
const iterator_range_detail::iterator_range_tag&
>,
is_convertible<
const SinglePassRange2&,
const iterator_range_detail::iterator_range_tag&
>
>,
bool
>::type
operator==(const SinglePassRange1& l, const SinglePassRange2& r)
{
BOOST_RANGE_CONCEPT_ASSERT((
boost::SinglePassRangeConcept<const SinglePassRange1>));
BOOST_RANGE_CONCEPT_ASSERT((
boost::SinglePassRangeConcept<const SinglePassRange2>));
return boost::equal(l, r);
}
template< class IteratorT, class ForwardRange >
inline bool operator!=( const ForwardRange& l,
const iterator_range<IteratorT>& r )
template<class SinglePassRange1, class SinglePassRange2>
inline BOOST_DEDUCED_TYPENAME enable_if<
mpl::or_<
is_convertible<
const SinglePassRange1&,
const iterator_range_detail::iterator_range_tag&
>,
is_convertible<
const SinglePassRange2&,
const iterator_range_detail::iterator_range_tag&
>
>,
bool
>::type
operator!=(const SinglePassRange1& l, const SinglePassRange2& r)
{
BOOST_RANGE_CONCEPT_ASSERT((
boost::SinglePassRangeConcept<const SinglePassRange1>));
BOOST_RANGE_CONCEPT_ASSERT((
boost::SinglePassRangeConcept<const SinglePassRange2>));
return !boost::equal(l, r);
}
template< class IteratorT, class ForwardRange >
inline bool operator<( const ForwardRange& l,
const iterator_range<IteratorT>& r )
template<class SinglePassRange1, class SinglePassRange2>
inline BOOST_DEDUCED_TYPENAME enable_if<
mpl::or_<
is_convertible<
const SinglePassRange1&,
const iterator_range_detail::iterator_range_tag&
>,
is_convertible<
const SinglePassRange2&,
const iterator_range_detail::iterator_range_tag&
>
>,
bool
>::type
operator<(const SinglePassRange1& l, const SinglePassRange2& r)
{
BOOST_RANGE_CONCEPT_ASSERT((
boost::SinglePassRangeConcept<const SinglePassRange1>));
BOOST_RANGE_CONCEPT_ASSERT((
boost::SinglePassRangeConcept<const SinglePassRange2>));
return iterator_range_detail::less_than(l, r);
}
template< class IteratorT, class ForwardRange >
inline bool operator<=( const ForwardRange& l,
const iterator_range<IteratorT>& r )
template<class SinglePassRange1, class SinglePassRange2>
inline BOOST_DEDUCED_TYPENAME enable_if<
mpl::or_<
is_convertible<
const SinglePassRange1&,
const iterator_range_detail::iterator_range_tag&
>,
is_convertible<
const SinglePassRange2&,
const iterator_range_detail::iterator_range_tag&
>
>,
bool
>::type
operator<=(const SinglePassRange1& l, const SinglePassRange2& r)
{
BOOST_RANGE_CONCEPT_ASSERT((
boost::SinglePassRangeConcept<const SinglePassRange1>));
BOOST_RANGE_CONCEPT_ASSERT((
boost::SinglePassRangeConcept<const SinglePassRange2>));
return iterator_range_detail::less_or_equal_than(l, r);
}
template< class IteratorT, class ForwardRange >
inline bool operator>( const ForwardRange& l,
const iterator_range<IteratorT>& r )
template<class SinglePassRange1, class SinglePassRange2>
inline BOOST_DEDUCED_TYPENAME enable_if<
mpl::or_<
is_convertible<
const SinglePassRange1&,
const iterator_range_detail::iterator_range_tag&
>,
is_convertible<
const SinglePassRange2&,
const iterator_range_detail::iterator_range_tag&
>
>,
bool
>::type
operator>(const SinglePassRange1& l, const SinglePassRange2& r)
{
BOOST_RANGE_CONCEPT_ASSERT((
boost::SinglePassRangeConcept<const SinglePassRange1>));
BOOST_RANGE_CONCEPT_ASSERT((
boost::SinglePassRangeConcept<const SinglePassRange2>));
return iterator_range_detail::greater_than(l, r);
}
template< class IteratorT, class ForwardRange >
inline bool operator>=( const ForwardRange& l,
const iterator_range<IteratorT>& r )
template<class SinglePassRange1, class SinglePassRange2>
inline BOOST_DEDUCED_TYPENAME enable_if<
mpl::or_<
is_convertible<
const SinglePassRange1&,
const iterator_range_detail::iterator_range_tag&
>,
is_convertible<
const SinglePassRange2&,
const iterator_range_detail::iterator_range_tag&
>
>,
bool
>::type
operator>=(const SinglePassRange1& l, const SinglePassRange2& r)
{
BOOST_RANGE_CONCEPT_ASSERT((
boost::SinglePassRangeConcept<const SinglePassRange1>));
BOOST_RANGE_CONCEPT_ASSERT((
boost::SinglePassRangeConcept<const SinglePassRange2>));
return iterator_range_detail::greater_or_equal_than(l, r);
}
#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
#else
template< class Iterator1T, class Iterator2T >
inline bool operator==( const iterator_range<Iterator1T>& l,
const iterator_range<Iterator2T>& r )
{
return boost::equal( l, r );
}
template< class IteratorT, class ForwardRange >
inline bool operator==( const iterator_range<IteratorT>& l,
const ForwardRange& r )
{
return boost::equal( l, r );
}
template< class Iterator1T, class Iterator2T >
inline bool operator!=( const iterator_range<Iterator1T>& l,
const iterator_range<Iterator2T>& r )
{
return !boost::equal( l, r );
}
template< class IteratorT, class ForwardRange >
inline bool operator!=( const iterator_range<IteratorT>& l,
const ForwardRange& r )
{
return !boost::equal( l, r );
}
template< class Iterator1T, class Iterator2T >
inline bool operator<( const iterator_range<Iterator1T>& l,
const iterator_range<Iterator2T>& r )
{
return iterator_range_detail::less_than( l, r );
}
template< class IteratorT, class ForwardRange >
inline bool operator<( const iterator_range<IteratorT>& l,
const ForwardRange& r )
{
return iterator_range_detail::less_than( l, r );
}
template< class Iterator1T, class Iterator2T >
inline bool operator<=( const iterator_range<Iterator1T>& l,
const iterator_range<Iterator2T>& r )
{
return iterator_range_detail::less_or_equal_than( l, r );
}
template< class IteratorT, class ForwardRange >
inline bool operator<=( const iterator_range<IteratorT>& l,
const ForwardRange& r )
{
return iterator_range_detail::less_or_equal_than( l, r );
}
template< class Iterator1T, class Iterator2T >
inline bool operator>( const iterator_range<Iterator1T>& l,
const iterator_range<Iterator2T>& r )
{
return iterator_range_detail::greater_than( l, r );
}
template< class IteratorT, class ForwardRange >
inline bool operator>( const iterator_range<IteratorT>& l,
const ForwardRange& r )
{
return iterator_range_detail::greater_than( l, r );
}
template< class Iterator1T, class Iterator2T >
inline bool operator>=( const iterator_range<Iterator1T>& l,
const iterator_range<Iterator2T>& r )
{
return iterator_range_detail::greater_or_equal_than( l, r );
}
template< class IteratorT, class ForwardRange >
inline bool operator>=( const iterator_range<IteratorT>& l,
const ForwardRange& r )
{
return iterator_range_detail::greater_or_equal_than( l, r );
}
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
// iterator range utilities -----------------------------------------//
//! iterator_range construct helper
@ -599,7 +708,6 @@ namespace boost
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
{
//BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" );
return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
}
@ -611,7 +719,6 @@ namespace boost
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
{
//BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" );
return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
}
@ -621,7 +728,6 @@ namespace boost
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
{
//BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" );
return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
}

View File

@ -0,0 +1,114 @@
// Boost.Range library
//
// Copyright Adam D. Walling 2012. 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_MFC_MAP_HPP
#define BOOST_RANGE_ADAPTOR_MFC_MAP_HPP
#if !defined(BOOST_RANGE_MFC_NO_CPAIR)
#include <boost/range/mfc.hpp>
#include <boost/range/adaptor/map.hpp>
namespace boost
{
namespace range_detail
{
// CMap and CMapStringToString range iterators return CPair,
// which has a key and value member. Other MFC range iterators
// already return adapted std::pair objects. This allows usage
// of the map_keys and map_values range adaptors with CMap
// and CMapStringToString
// CPair has a VALUE value member, and a KEY key member; we will
// use VALUE& as the result_type consistent with CMap::operator[]
// specialization for CMap
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
struct select_first< CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> >
{
typedef BOOST_DEDUCED_TYPENAME CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> map_type;
typedef BOOST_DEDUCED_TYPENAME range_reference<const map_type>::type argument_type;
typedef BOOST_DEDUCED_TYPENAME const KEY& result_type;
result_type operator()( argument_type r ) const
{
return r.key;
}
};
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
struct select_second_mutable< CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> >
{
typedef BOOST_DEDUCED_TYPENAME CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> map_type;
typedef BOOST_DEDUCED_TYPENAME range_reference<map_type>::type argument_type;
typedef BOOST_DEDUCED_TYPENAME VALUE& result_type;
result_type operator()( argument_type r ) const
{
return r.value;
}
};
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
struct select_second_const< CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> >
{
typedef BOOST_DEDUCED_TYPENAME CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> map_type;
typedef BOOST_DEDUCED_TYPENAME range_reference<const map_type>::type argument_type;
typedef BOOST_DEDUCED_TYPENAME const VALUE& result_type;
result_type operator()( argument_type r ) const
{
return r.value;
}
};
// specialization for CMapStringToString
template<>
struct select_first< CMapStringToString >
{
typedef range_reference<const CMapStringToString>::type argument_type;
typedef const CString& result_type;
result_type operator()( argument_type r ) const
{
return r.key;
}
};
template<>
struct select_second_mutable< CMapStringToString >
{
typedef range_reference<CMapStringToString>::type argument_type;
typedef CString& result_type;
result_type operator()( argument_type r ) const
{
return r.value;
}
};
template<>
struct select_second_const< CMapStringToString >
{
typedef range_reference<const CMapStringToString>::type argument_type;
typedef const CString& result_type;
result_type operator()( argument_type r ) const
{
return r.value;
}
};
} // 'range_detail'
} // 'boost'
#endif // !defined(BOOST_RANGE_MFC_NO_CPAIR)
#endif

View File

@ -1,14 +1,8 @@
///////////////////////////////////////////////////////////////////////////////
/// \file algorithm.hpp
/// Contains range-based versions of the std algorithms
//
/////////////////////////////////////////////////////////////////////////////
// Copyright 2009 Neil Groves.
// Copyright 2009-2014 Neil Groves.
// 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)
//
// Copyright 2006 Thorsten Ottosen.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@ -18,7 +12,9 @@
// 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)
//
// Contains range-based versions of the numeric std algorithms
//
#if defined(_MSC_VER)
#pragma once
#endif
@ -30,8 +26,10 @@
#include <boost/assert.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/category.hpp>
#include <boost/range/concepts.hpp>
#include <boost/range/distance.hpp>
#include <boost/range/size.hpp>
#include <numeric>
@ -40,41 +38,101 @@ namespace boost
template<class SinglePassRange, class Value>
inline Value accumulate(const SinglePassRange& rng, Value init)
{
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange> ));
BOOST_RANGE_CONCEPT_ASSERT((
SinglePassRangeConcept<const SinglePassRange>));
return std::accumulate(boost::begin(rng), boost::end(rng), init);
}
template<class SinglePassRange, class Value, class BinaryOperation>
inline Value accumulate( const SinglePassRange& rng, Value init, BinaryOperation op )
inline Value accumulate(const SinglePassRange& rng, Value init,
BinaryOperation op)
{
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange> ));
BOOST_RANGE_CONCEPT_ASSERT((
SinglePassRangeConcept<const SinglePassRange> ));
return std::accumulate(boost::begin(rng), boost::end(rng), init, op);
}
template< class SinglePassRange1, class SinglePassRange2, class Value >
inline Value inner_product( const SinglePassRange1& rng1, const SinglePassRange2& rng2, Value init )
namespace range_detail
{
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange1> ));
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange2> ));
BOOST_ASSERT( boost::distance(rng2) >= boost::distance(rng1) );
return std::inner_product( boost::begin(rng1), boost::end(rng1),
template<class SinglePassRange1, class SinglePassRange2>
inline bool inner_product_precondition(
const SinglePassRange1&,
const SinglePassRange2&,
std::input_iterator_tag,
std::input_iterator_tag)
{
return true;
}
template<class SinglePassRange1, class SinglePassRange2>
inline bool inner_product_precondition(
const SinglePassRange1& rng1,
const SinglePassRange2& rng2,
std::forward_iterator_tag,
std::forward_iterator_tag)
{
return boost::size(rng2) >= boost::size(rng1);
}
} // namespace range_detail
template<
class SinglePassRange1,
class SinglePassRange2,
class Value
>
inline Value inner_product(
const SinglePassRange1& rng1,
const SinglePassRange2& rng2,
Value init)
{
BOOST_RANGE_CONCEPT_ASSERT((
SinglePassRangeConcept<const SinglePassRange1>));
BOOST_RANGE_CONCEPT_ASSERT((
SinglePassRangeConcept<const SinglePassRange2>));
BOOST_ASSERT(
range_detail::inner_product_precondition(
rng1, rng2,
typename range_category<const SinglePassRange1>::type(),
typename range_category<const SinglePassRange2>::type()));
return std::inner_product(
boost::begin(rng1), boost::end(rng1),
boost::begin(rng2), init);
}
template< class SinglePassRange1,
template<
class SinglePassRange1,
class SinglePassRange2,
class Value,
class BinaryOperation1, class BinaryOperation2 >
inline Value inner_product( const SinglePassRange1& rng1, const SinglePassRange2& rng2,
class BinaryOperation1,
class BinaryOperation2
>
inline Value inner_product(
const SinglePassRange1& rng1,
const SinglePassRange2& rng2,
Value init,
BinaryOperation1 op1, BinaryOperation2 op2 )
BinaryOperation1 op1,
BinaryOperation2 op2)
{
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange1> ));
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange2> ));
BOOST_ASSERT( boost::distance(rng2) >= boost::distance(rng1) );
BOOST_RANGE_CONCEPT_ASSERT((
SinglePassRangeConcept<const SinglePassRange1>));
return std::inner_product( boost::begin(rng1), boost::end(rng1),
BOOST_RANGE_CONCEPT_ASSERT((
SinglePassRangeConcept<const SinglePassRange2>));
BOOST_ASSERT(
range_detail::inner_product_precondition(
rng1, rng2,
typename range_category<const SinglePassRange1>::type(),
typename range_category<const SinglePassRange2>::type()));
return std::inner_product(
boost::begin(rng1), boost::end(rng1),
boost::begin(rng2), init, op1, op2);
}
@ -82,37 +140,49 @@ namespace boost
inline OutputIterator partial_sum(const SinglePassRange& rng,
OutputIterator result)
{
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange> ));
BOOST_RANGE_CONCEPT_ASSERT((
SinglePassRangeConcept<const SinglePassRange>));
return std::partial_sum(boost::begin(rng), boost::end(rng), result);
}
template<class SinglePassRange, class OutputIterator, class BinaryOperation>
inline OutputIterator partial_sum ( const SinglePassRange& rng, OutputIterator result,
inline OutputIterator partial_sum(
const SinglePassRange& rng,
OutputIterator result,
BinaryOperation op)
{
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange> ));
BOOST_RANGE_CONCEPT_ASSERT((
SinglePassRangeConcept<const SinglePassRange>));
return std::partial_sum(boost::begin(rng), boost::end(rng), result, op);
}
template<class SinglePassRange, class OutputIterator>
inline OutputIterator adjacent_difference ( const SinglePassRange& rng,
inline OutputIterator adjacent_difference(
const SinglePassRange& rng,
OutputIterator result)
{
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange> ));
BOOST_RANGE_CONCEPT_ASSERT((
SinglePassRangeConcept<const SinglePassRange>));
return std::adjacent_difference(boost::begin(rng), boost::end(rng),
result);
}
template<class SinglePassRange, class OutputIterator, class BinaryOperation>
inline OutputIterator adjacent_difference ( const SinglePassRange& rng,
inline OutputIterator adjacent_difference(
const SinglePassRange& rng,
OutputIterator result,
BinaryOperation op)
{
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<SinglePassRange> ));
BOOST_RANGE_CONCEPT_ASSERT((
SinglePassRangeConcept<const SinglePassRange>));
return std::adjacent_difference(boost::begin(rng), boost::end(rng),
result, op);
}
}
} // namespace boost
#endif

View File

@ -19,24 +19,39 @@
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size_type.hpp>
#include <boost/range/detail/has_member_size.hpp>
#include <boost/assert.hpp>
#include <boost/cstdint.hpp>
#include <boost/utility.hpp>
namespace boost
{
namespace range_detail
{
template<class SinglePassRange>
inline BOOST_DEDUCED_TYPENAME range_size<const SinglePassRange>::type
inline typename enable_if<
has_member_size<SinglePassRange>,
typename range_size<const SinglePassRange>::type
>::type
range_calculate_size(const SinglePassRange& rng)
{
BOOST_ASSERT( (boost::end(rng) - boost::begin(rng)) >= 0 &&
"reachability invariant broken!" );
return boost::end(rng) - boost::begin(rng);
return rng.size();
}
template<class SinglePassRange>
inline typename disable_if<
has_member_size<SinglePassRange>,
typename range_size<const SinglePassRange>::type
>::type
range_calculate_size(const SinglePassRange& rng)
{
return std::distance(boost::begin(rng), boost::end(rng));
}
}
template<class SinglePassRange>
inline BOOST_DEDUCED_TYPENAME range_size<const SinglePassRange>::type
inline typename range_size<const SinglePassRange>::type
size(const SinglePassRange& rng)
{
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \

View File

@ -33,12 +33,16 @@ namespace boost
{
template< class ForwardRange >
class sub_range : public iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type >
class sub_range
: public iterator_range<
BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
>
{
typedef BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type iterator_t;
typedef iterator_range< iterator_t > base;
typedef BOOST_DEDUCED_TYPENAME base::impl impl;
public:
typedef BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type value_type;
typedef BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type iterator;
@ -47,14 +51,22 @@ namespace boost
typedef BOOST_DEDUCED_TYPENAME range_size<ForwardRange>::type size_type;
typedef BOOST_DEDUCED_TYPENAME base::reference reference;
public: // for return value of front/back
typedef BOOST_DEDUCED_TYPENAME
boost::mpl::if_< boost::is_reference<reference>,
const BOOST_DEDUCED_TYPENAME boost::remove_reference<reference>::type&,
reference >::type const_reference;
private:
template<class Source>
struct is_compatible_range
: is_convertible<
BOOST_DEDUCED_TYPENAME mpl::eval_if<
has_range_iterator<Source>,
range_iterator<Source>,
mpl::identity<void>
>::type,
iterator
>
{
};
public:
sub_range() : base()
sub_range()
{ }
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500) )
@ -64,7 +76,12 @@ namespace boost
#endif
template< class ForwardRange2 >
sub_range( ForwardRange2& r ) :
sub_range(
ForwardRange2& r,
BOOST_DEDUCED_TYPENAME enable_if<
is_compatible_range<ForwardRange2>
>::type* = 0
) :
#if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 800 )
base( impl::adl_begin( r ), impl::adl_end( r ) )
@ -74,7 +91,12 @@ namespace boost
{ }
template< class ForwardRange2 >
sub_range( const ForwardRange2& r ) :
sub_range(
const ForwardRange2& r,
BOOST_DEDUCED_TYPENAME enable_if<
is_compatible_range<const ForwardRange2>
>::type* = 0
) :
#if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 800 )
base( impl::adl_begin( r ), impl::adl_end( r ) )
@ -89,14 +111,22 @@ namespace boost
{ }
template<class ForwardRange2>
sub_range& operator=( ForwardRange2& r )
BOOST_DEDUCED_TYPENAME enable_if<
is_compatible_range<ForwardRange2>,
sub_range&
>::type
operator=(ForwardRange2& r)
{
base::operator=( r );
return *this;
}
template<class ForwardRange2>
sub_range& operator=( const ForwardRange2& r )
BOOST_DEDUCED_TYPENAME enable_if<
is_compatible_range<const ForwardRange2>,
sub_range&
>::type
operator=( const ForwardRange2& r )
{
base::operator=( r );
return *this;
@ -107,71 +137,8 @@ namespace boost
base::operator=( static_cast<const base&>(r) );
return *this;
}
public:
iterator begin() { return base::begin(); }
const_iterator begin() const { return base::begin(); }
iterator end() { return base::end(); }
const_iterator end() const { return base::end(); }
difference_type size() const { return base::size(); }
public: // convenience
reference front()
{
return base::front();
}
const_reference front() const
{
return base::front();
}
reference back()
{
return base::back();
}
const_reference back() const
{
return base::back();
}
reference operator[]( difference_type sz )
{
return base::operator[](sz);
}
const_reference operator[]( difference_type sz ) const
{
return base::operator[](sz);
}
};
template< class ForwardRange, class ForwardRange2 >
inline bool operator==( const sub_range<ForwardRange>& l,
const sub_range<ForwardRange2>& r )
{
return boost::equal( l, r );
}
template< class ForwardRange, class ForwardRange2 >
inline bool operator!=( const sub_range<ForwardRange>& l,
const sub_range<ForwardRange2>& r )
{
return !boost::equal( l, r );
}
template< class ForwardRange, class ForwardRange2 >
inline bool operator<( const sub_range<ForwardRange>& l,
const sub_range<ForwardRange2>& r )
{
return iterator_range_detail::less_than( l, r );
}
} // namespace 'boost'
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))

View File

@ -44,9 +44,20 @@ test-suite range :
[ range-test adaptor_test/sliced ]
[ range-test adaptor_test/strided ]
[ range-test adaptor_test/strided2 ]
[ range-test adaptor_test/ticket_6742_transformed_c4789_warning ]
[ range-test adaptor_test/ticket_8676_sliced_transformed ]
[ range-test adaptor_test/ticket_9519_strided_reversed ]
[ range-test adaptor_test/tokenized ]
[ range-test adaptor_test/transformed ]
[ range-test adaptor_test/type_erased ]
[ range-test adaptor_test/type_erased_abstract ]
[ range-test adaptor_test/type_erased_brackets ]
[ range-test adaptor_test/type_erased_mix_values ]
[ range-test adaptor_test/type_erased_tparam_conv ]
[ range-test adaptor_test/type_erased_single_pass ]
[ range-test adaptor_test/type_erased_forward ]
[ range-test adaptor_test/type_erased_bidirectional ]
[ range-test adaptor_test/type_erased_random_access ]
[ range-test adaptor_test/uniqued ]
[ range-test adaptor_test/adjacent_filtered_example ]
[ range-test adaptor_test/copied_example ]
@ -149,6 +160,7 @@ test-suite range :
[ range-test istream_range ]
[ range-test iterator_pair ]
[ range-test iterator_range ]
[ range-test iterator_range_variant ]
# [ range-test mfc : <include>$(VC71_ROOT)/atlmfc/include ]
[ range-test join ]
[ range-test partial_workaround ]
@ -161,6 +173,8 @@ test-suite range :
[ range-test ticket_5544_terminate_irange ]
[ range-test ticket_5547 ]
[ range-test ticket_5556_is_sorted_namespace ]
[ range-test ticket_5811_indirected_optional ]
[ range-test ticket_6715_iterator_range_equality ]
[ range-test ticket_6944 ]
;

View File

@ -11,6 +11,9 @@
// The strided_defect_Trac5014 test case is a modified version of a test case
// contributed by Michel Morin as part of the trac ticket.
//
// The deque test case has been removed due to erroneous standard library
// implementations causing test failures.
//
#include <boost/range/adaptor/strided.hpp>
#include <boost/config.hpp>
@ -21,7 +24,6 @@
#include <boost/range/algorithm_ext.hpp>
#include <algorithm>
#include <deque>
#include <vector>
namespace boost
@ -135,8 +137,15 @@ namespace boost
boost::ignore_unused_variable_warning(rng);
typedef BOOST_DEDUCED_TYPENAME boost::range_iterator<strided_range_t>::type iter_t;
iter_t first(boost::begin(c), boost::begin(c), boost::end(c), 0);
iter_t last(boost::begin(c), boost::end(c), boost::end(c), 0);
typedef BOOST_DEDUCED_TYPENAME boost::iterator_traversal<
BOOST_DEDUCED_TYPENAME Container::const_iterator
>::type container_traversal_tag;
iter_t first = boost::range_detail::make_begin_strided_iterator(
c, 0, container_traversal_tag());
iter_t last = boost::range_detail::make_end_strided_iterator(
c, 0, container_traversal_tag());
iter_t it = first;
for (int i = 0; i < 10; ++i, ++it)
@ -160,7 +169,6 @@ namespace boost
void strided_test()
{
strided_test_impl< std::vector<int> >();
strided_test_impl< std::deque<int> >();
strided_test_impl< std::list<int> >();
}

View File

@ -0,0 +1,69 @@
// Boost.Range library
//
// Copyright Neil Groves 2014. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// For more information, see http://www.boost.org/libs/range/
//
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/operator.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm_ext/push_back.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
#include <iterator>
#include <iostream>
#include <vector>
namespace
{
struct test_struct
{
double x;
double y;
};
struct get_x
{
typedef double result_type;
double operator()(const test_struct& s) const
{
return s.x;
}
};
void range_transformed_warning()
{
using namespace boost::phoenix::arg_names;
using namespace boost::adaptors;
test_struct t;
t.x = 2.0;
t.y = -4.0;
std::vector<test_struct> v(10u, t);
std::vector<double> output1;
boost::push_back(output1, v | transformed((&arg1)->*& test_struct::x));
std::vector<double> output2;
boost::push_back(output2, v | transformed(get_x()));
BOOST_CHECK_EQUAL_COLLECTIONS(
output1.begin(), output1.end(),
output2.begin(), output2.end());
}
} // anonymous namespace
boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
boost::unit_test::test_suite* test
= BOOST_TEST_SUITE( "Range adaptors - transformed warning" );
test->add(BOOST_TEST_CASE(&range_transformed_warning));
return test;
}

View File

@ -0,0 +1,56 @@
// Boost.Range library
//
// Copyright Neil Groves 2014. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// For more information, see http://www.boost.org/libs/range/
//
#include <boost/range/adaptor/sliced.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm_ext/push_back.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
#include <vector>
namespace
{
struct identity
{
typedef int result_type;
result_type operator()(int i) const { return i; }
};
void sliced_and_transformed()
{
using namespace boost::adaptors;
std::vector<int> input;
for (int i = 0; i < 10; ++i)
input.push_back(i);
std::vector<int> out1;
boost::push_back(out1, input | sliced(2, 8)
| transformed(identity()));
std::vector<int> out2;
boost::push_back(out2, input | transformed(identity())
| sliced(2, 8));
BOOST_CHECK_EQUAL_COLLECTIONS(out1.begin(), out1.end(),
out2.begin(), out2.end());
}
} // anonymous namespace
boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
boost::unit_test::test_suite* test
= BOOST_TEST_SUITE( "Range adaptors - sliced and transformed" );
test->add(BOOST_TEST_CASE(&sliced_and_transformed));
return test;
}

View File

@ -0,0 +1,67 @@
// Boost.Range library
//
// Copyright Neil Groves 2014. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// For more information, see http://www.boost.org/libs/range/
//
// Credit goes to Eric Niebler for providing an example to demonstrate this
// issue. This has been trivially modified to create this test case.
//
#include <boost/range/adaptor/strided.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/algorithm_ext/push_back.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
#include <list>
#include <vector>
#include <numeric>
namespace boost
{
namespace
{
void ticket_9519_strided_reversed_test()
{
using namespace boost::adaptors;
std::vector<int> vi;
for (int i = 0; i < 50; ++i)
{
vi.push_back(i);
}
std::vector<int> output;
boost::push_back(output, vi | strided(3) | reversed);
std::list<int> reference;
for (int i = 0; i < 50; i += 3)
{
reference.push_front(i);
}
BOOST_CHECK_EQUAL_COLLECTIONS(output.begin(), output.end(),
reference.begin(), reference.end());
}
} // anonymous namespace
} // namespace boost
boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
boost::unit_test::test_suite* test
= BOOST_TEST_SUITE(
"RangeTestSuite.adaptor.ticket_9519_strided_reversed");
test->add(BOOST_TEST_CASE(&boost::ticket_9519_strided_reversed_test));
return test;
}

View File

@ -6,104 +6,17 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/range/adaptor/type_erased.hpp>
#include "type_erased_test.hpp"
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/range/algorithm_ext.hpp>
#include <boost/range/algorithm/fill.hpp>
#include <boost/assign.hpp>
#include <boost/array.hpp>
#include <algorithm>
#include <list>
#include <set>
#include <vector>
namespace boost_range_adaptor_type_erased_test
{
class MockType
namespace
{
public:
MockType()
: m_x(0)
{
}
MockType(int x)
: m_x(x)
{
}
int get() const { return m_x; }
inline bool operator==(const MockType& other) const
{
return m_x == other.m_x;
}
inline bool operator!=(const MockType& other) const
{
return m_x != other.m_x;
}
private:
int m_x;
};
inline std::ostream& operator<<(std::ostream& out, const MockType& obj)
{
out << obj.get();
return out;
}
template<class Container>
void test_type_erased_impl(Container& c)
{
using namespace boost::adaptors;
typedef typename boost::range_value<Container>::type value_type;
typedef typename boost::adaptors::type_erased<> type_erased_t;
std::vector<value_type> output;
boost::push_back(output, boost::adaptors::type_erase(c, type_erased_t()));
BOOST_CHECK_EQUAL_COLLECTIONS( output.begin(), output.end(),
c.begin(), c.end() );
output.clear();
boost::push_back(output, c | type_erased_t());
BOOST_CHECK_EQUAL_COLLECTIONS( output.begin(), output.end(),
c.begin(), c.end() );
}
template<class Container>
void test_const_and_mutable(Container& c)
{
test_type_erased_impl(c);
const Container& const_c = c;
test_type_erased_impl(const_c);
}
template<class Container>
void test_driver()
{
using namespace boost::assign;
typedef typename boost::range_value<Container>::type value_type;
Container c;
test_const_and_mutable(c);
c += value_type(1);
test_const_and_mutable(c);
c += value_type(2);
test_const_and_mutable(c);
}
void test_type_erased()
{
@ -114,368 +27,18 @@ namespace boost_range_adaptor_type_erased_test
test_driver< std::vector<MockType> >();
}
template<
class Traversal
, class Container
>
void test_writeable(Container&, boost::single_pass_traversal_tag)
{}
template<
class Traversal
, class Container
>
void test_writeable(Container& source, boost::forward_traversal_tag)
{
using namespace boost::adaptors;
typedef typename boost::range_value<Container>::type value_type;
typedef typename boost::range_difference<Container>::type difference_type;
typedef typename boost::range_reference<Container>::type mutable_reference_type;
typedef boost::any_range<
value_type
, Traversal
, mutable_reference_type
, difference_type
> mutable_any_range;
mutable_any_range r = source | boost::adaptors::type_erased<>();
std::vector<value_type> output_test;
boost::fill(r, value_type(1));
BOOST_CHECK_EQUAL( boost::distance(r), boost::distance(source) );
std::vector<value_type> reference_output(source.size(), value_type(1));
BOOST_CHECK_EQUAL_COLLECTIONS( reference_output.begin(), reference_output.end(),
r.begin(), r.end() );
}
template<
class Container
, class Traversal
, class Buffer
>
void test_type_erased_impl()
{
using namespace boost::adaptors;
typedef Buffer buffer_type;
typedef typename boost::range_value<Container>::type value_type;
typedef typename boost::any_range_type_generator<
Container
, boost::use_default
, Traversal
, boost::use_default
, boost::use_default
, Buffer
>::type mutable_any_range;
typedef typename boost::any_range_type_generator<
const Container
, boost::use_default
, Traversal
, boost::use_default
, boost::use_default
, Buffer
>::type const_any_range;
typedef boost::adaptors::type_erased<
boost::use_default
, Traversal
, boost::use_default
, boost::use_default
, Buffer
> type_erased_t;
Container source;
for (int i = 0; i < 10; ++i)
source.push_back(value_type(i));
mutable_any_range r(source);
BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
r.begin(), r.end() );
r = mutable_any_range();
BOOST_CHECK_EQUAL( r.empty(), true );
r = source | type_erased_t();
BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
r.begin(), r.end() );
r = mutable_any_range();
r = boost::adaptors::type_erase(source, type_erased_t());
BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
r.begin(), r.end() );
r = mutable_any_range();
test_writeable<Traversal>(source, Traversal());
// convert and construct a const any_range from a mutable source
// range
const_any_range cr(source);
BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
cr.begin(), cr.end() );
// assign an empty range and ensure that this correctly results
// in an empty range. This is important for the validity of
// the rest of the tests.
cr = const_any_range();
BOOST_CHECK_EQUAL( cr.empty(), true );
// Test the pipe type_erased adaptor from a constant source
// range to a constant any_range
const Container& const_source = source;
cr = const_any_range();
cr = const_source | type_erased_t();
BOOST_CHECK_EQUAL_COLLECTIONS( const_source.begin(), const_source.end(),
cr.begin(), cr.end() );
// Test the pipe type erased adaptor from a mutable source
// range to a constant any_range
cr = const_any_range();
cr = source | type_erased_t();
BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
cr.begin(), cr.end() );
// Use the function form of the type_erase adaptor from a constant
// source range
cr = const_any_range();
cr = boost::adaptors::type_erase(const_source, type_erased_t());
BOOST_CHECK_EQUAL_COLLECTIONS( const_source.begin(), const_source.end(),
cr.begin(), cr.end() );
// Assignment from mutable to const...
cr = const_any_range();
cr = r;
BOOST_CHECK_EQUAL_COLLECTIONS( cr.begin(), cr.end(),
r.begin(), r.end() );
// Converting copy from mutable to const...
cr = const_any_range();
cr = const_any_range(r);
BOOST_CHECK_EQUAL_COLLECTIONS( cr.begin(), cr.end(),
r.begin(), r.end() );
}
template<
class Container
, class Traversal
, class Buffer
>
class test_type_erased_impl_fn
{
public:
typedef void result_type;
void operator()()
{
test_type_erased_impl< Container, Traversal, Buffer >();
}
};
template<
class Container
, class Traversal
>
void test_type_erased_exercise_buffer_types()
{
using boost::any_iterator_default_buffer;
using boost::any_iterator_buffer;
using boost::any_iterator_heap_only_buffer;
using boost::any_iterator_stack_only_buffer;
test_type_erased_impl_fn< Container, Traversal, any_iterator_default_buffer >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_heap_only_buffer >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<1> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<2> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<32> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<64> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<128> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_stack_only_buffer<128> >()();
}
void test_type_erased_single_pass()
{
test_type_erased_exercise_buffer_types< std::list<int>, boost::single_pass_traversal_tag >();
test_type_erased_exercise_buffer_types< std::deque<int>, boost::single_pass_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<int>, boost::single_pass_traversal_tag >();
test_type_erased_exercise_buffer_types< std::list<MockType>, boost::single_pass_traversal_tag >();
test_type_erased_exercise_buffer_types< std::deque<MockType>, boost::single_pass_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<MockType>, boost::single_pass_traversal_tag >();
}
void test_type_erased_forward()
{
test_type_erased_exercise_buffer_types< std::list<int>, boost::forward_traversal_tag >();
test_type_erased_exercise_buffer_types< std::deque<int>, boost::forward_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<int>, boost::forward_traversal_tag >();
test_type_erased_exercise_buffer_types< std::list<MockType>, boost::forward_traversal_tag >();
test_type_erased_exercise_buffer_types< std::deque<MockType>, boost::forward_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<MockType>, boost::forward_traversal_tag >();
}
void test_type_erased_bidirectional()
{
test_type_erased_exercise_buffer_types< std::list<int>, boost::bidirectional_traversal_tag >();
test_type_erased_exercise_buffer_types< std::deque<int>, boost::bidirectional_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<int>, boost::bidirectional_traversal_tag >();
test_type_erased_exercise_buffer_types< std::list<MockType>, boost::bidirectional_traversal_tag >();
test_type_erased_exercise_buffer_types< std::deque<MockType>, boost::bidirectional_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<MockType>, boost::bidirectional_traversal_tag >();
}
void test_type_erased_random_access()
{
test_type_erased_exercise_buffer_types< std::deque<int>, boost::random_access_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<int>, boost::random_access_traversal_tag >();
test_type_erased_exercise_buffer_types< std::deque<MockType>, boost::random_access_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<MockType>, boost::random_access_traversal_tag >();
}
void test_type_erased_multiple_different_template_parameter_conversion()
{
typedef boost::any_range<
int
, boost::random_access_traversal_tag
, int&
, std::ptrdiff_t
> source_range_type;
typedef boost::any_range<
int
, boost::single_pass_traversal_tag
, const int&
, std::ptrdiff_t
> target_range_type;
source_range_type source;
// Converting via construction
target_range_type t1(source);
// Converting via assignment
target_range_type t2;
t2 = source;
// Converting via construction to a type with a reference type
// that is a value
typedef boost::any_range<
int
, boost::single_pass_traversal_tag
, int
, std::ptrdiff_t
> target_range2_type;
target_range2_type t3(source);
target_range2_type t4;
t4 = source;
}
template<
class Traversal
, class ValueType
, class SourceValueType
, class SourceReference
, class TargetValueType
, class TargetReference
>
void test_type_erased_mix_values_impl()
{
typedef std::vector< ValueType > Container;
typedef typename boost::any_range_type_generator<
Container
, SourceValueType
, Traversal
, SourceReference
>::type source_type;
typedef typename boost::any_range_type_generator<
Container
, TargetValueType
, Traversal
, TargetReference
>::type target_type;
Container test_data;
for (int i = 0; i < 10; ++i)
test_data.push_back(i);
const source_type source_data(test_data);
target_type t1(source_data);
BOOST_CHECK_EQUAL_COLLECTIONS( source_data.begin(), source_data.end(),
t1.begin(), t1.end() );
target_type t2;
t2 = source_data;
BOOST_CHECK_EQUAL_COLLECTIONS( source_data.begin(), source_data.end(),
t2.begin(), t2.end() );
}
template<class Traversal>
void test_type_erased_mix_values_driver()
{
test_type_erased_mix_values_impl< Traversal, int, char, const int&, short, const int& >();
test_type_erased_mix_values_impl< Traversal, int, int*, const int&, char, const int& >();
test_type_erased_mix_values_impl< Traversal, MockType, char, const MockType&, short, const MockType& >();
// In fact value type should have no effect in the eligibility
// for conversion, hence we should be able to convert it
// completely backwards!
test_type_erased_mix_values_impl< Traversal, int, short, const int&, char, const int& >();
test_type_erased_mix_values_impl< Traversal, int, char, const int&, int*, const int& >();
}
void test_type_erased_mix_values()
{
test_type_erased_mix_values_driver< boost::single_pass_traversal_tag >();
test_type_erased_mix_values_driver< boost::forward_traversal_tag >();
test_type_erased_mix_values_driver< boost::bidirectional_traversal_tag >();
test_type_erased_mix_values_driver< boost::random_access_traversal_tag >();
}
void test_type_erased_operator_brackets()
{
typedef boost::adaptors::type_erased<> type_erased_t;
std::vector<int> c;
for (int i = 0; i < 10; ++i)
c.push_back(i);
typedef boost::any_range<
int
, boost::random_access_traversal_tag
, int
, boost::range_difference< std::vector<int> >::type
, boost::use_default
> any_range_type;
any_range_type rng = c | type_erased_t();
for (int i = 0; i < 10; ++i)
{
BOOST_CHECK_EQUAL( rng[i], i );
}
}
}
} // anonymous namespace
} // namespace boost_range_adaptor_type_erased_test
boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
boost::unit_test::test_suite* test
= BOOST_TEST_SUITE( "RangeTestSuite.adaptor.type_erased" );
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased");
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased ) );
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_single_pass ) );
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_forward ) );
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_bidirectional ) );
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_random_access ) );
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_multiple_different_template_parameter_conversion ) );
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_mix_values ) );
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_operator_brackets ) );
test->add(BOOST_TEST_CASE(
&boost_range_adaptor_type_erased_test::test_type_erased));
return test;
}

View File

@ -0,0 +1,88 @@
// Boost.Range library
//
// Copyright Neil Groves 2014. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/range/adaptor/type_erased.hpp>
#include "type_erased_test.hpp"
#include <boost/test/unit_test.hpp>
#include <vector>
namespace boost_range_adaptor_type_erased_test
{
namespace
{
class dummy_interface
{
public:
virtual ~dummy_interface() { }
virtual void test() = 0;
protected:
dummy_interface() { }
private:
dummy_interface(const dummy_interface&);
void operator=(const dummy_interface&);
};
class dummy_impl
: public dummy_interface
{
public:
dummy_impl() { }
dummy_impl(const dummy_impl&) { }
dummy_impl& operator=(const dummy_impl&) { return *this; }
virtual void test() { }
};
typedef boost::any_range<
dummy_interface,
boost::random_access_traversal_tag,
dummy_interface&,
std::ptrdiff_t
> any_interface_range;
struct foo_dummy_interface_fn
{
void operator()(dummy_interface& iface)
{
iface.test();
}
};
void foo_test_dummy_interface_range(any_interface_range rng)
{
std::for_each(boost::begin(rng), boost::end(rng),
foo_dummy_interface_fn());
}
void test_type_erased_abstract()
{
std::vector<dummy_impl> v(10);
any_interface_range r(v);
foo_test_dummy_interface_range(r);
foo_test_dummy_interface_range(any_interface_range(v));
}
} // anonymous namespace
} // namespace boost_range_adaptor_type_erased_test
boost::unit_test::test_suite*
init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test
= BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_abstract");
test->add(
BOOST_TEST_CASE(
&boost_range_adaptor_type_erased_test::test_type_erased_abstract));
return test;
}

View File

@ -0,0 +1,57 @@
// Boost.Range library
//
// Copyright Neil Groves 2014. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/range/adaptor/type_erased.hpp>
#include "type_erased_test.hpp"
#include <boost/test/unit_test.hpp>
#include <list>
#include <deque>
#include <vector>
namespace boost_range_adaptor_type_erased_test
{
namespace
{
void test_bidirectional()
{
test_type_erased_exercise_buffer_types<
std::list<int>, boost::bidirectional_traversal_tag >();
test_type_erased_exercise_buffer_types<
std::deque<int>, boost::bidirectional_traversal_tag >();
test_type_erased_exercise_buffer_types<
std::vector<int>, boost::bidirectional_traversal_tag >();
test_type_erased_exercise_buffer_types<
std::list<MockType>, boost::bidirectional_traversal_tag >();
test_type_erased_exercise_buffer_types<
std::deque<MockType>, boost::bidirectional_traversal_tag >();
test_type_erased_exercise_buffer_types<
std::vector<MockType>, boost::bidirectional_traversal_tag >();
}
} // anonymous namespace
} // namespace boost_range_adaptor_type_erased_test
boost::unit_test::test_suite*
init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_bidirectional");
test->add(BOOST_TEST_CASE(
&boost_range_adaptor_type_erased_test::test_bidirectional));
return test;
}

View File

@ -0,0 +1,70 @@
// Boost.Range library
//
// Copyright Neil Groves 2014. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/range/adaptor/type_erased.hpp>
#include "type_erased_test.hpp"
#include <boost/test/unit_test.hpp>
#include <vector>
namespace boost_range_adaptor_type_erased_test
{
namespace
{
void test_operator_brackets()
{
typedef boost::adaptors::type_erased<> type_erased_t;
std::vector<int> c;
for (int i = 0; i < 10; ++i)
c.push_back(i);
typedef boost::any_range_type_generator<
std::vector<int> >::type any_range_type;
BOOST_STATIC_ASSERT((
boost::is_same<
int,
boost::range_value<any_range_type>::type
>::value
));
BOOST_STATIC_ASSERT((
boost::is_same<
boost::random_access_traversal_tag,
boost::iterator_traversal<
boost::range_iterator<any_range_type>::type
>::type
>::value
));
any_range_type rng = c | type_erased_t();
for (int i = 0; i < 10; ++i)
{
BOOST_CHECK_EQUAL(rng[i], i);
}
}
} // anonymous namespace
} // namespace boost_range_adaptor_type_erased_test
boost::unit_test::test_suite*
init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test
= BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_brackets");
test->add(
BOOST_TEST_CASE(
&boost_range_adaptor_type_erased_test::test_operator_brackets));
return test;
}

View File

@ -0,0 +1,57 @@
// Boost.Range library
//
// Copyright Neil Groves 2014. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/range/adaptor/type_erased.hpp>
#include "type_erased_test.hpp"
#include <boost/test/unit_test.hpp>
#include <deque>
#include <list>
#include <vector>
namespace boost_range_adaptor_type_erased_test
{
namespace
{
void test_forward()
{
test_type_erased_exercise_buffer_types<
std::list<int>, boost::forward_traversal_tag >();
test_type_erased_exercise_buffer_types<
std::deque<int>, boost::forward_traversal_tag >();
test_type_erased_exercise_buffer_types<
std::vector<int>, boost::forward_traversal_tag >();
test_type_erased_exercise_buffer_types<
std::list<MockType>, boost::forward_traversal_tag >();
test_type_erased_exercise_buffer_types<
std::deque<MockType>, boost::forward_traversal_tag >();
test_type_erased_exercise_buffer_types<
std::vector<MockType>, boost::forward_traversal_tag >();
}
} // anonymous namespace
} // namespace boost_range_adaptor_type_erased_test
boost::unit_test::test_suite*
init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE( "RangeTestSuite.adaptor.type_erased_forward" );
test->add(BOOST_TEST_CASE(
&boost_range_adaptor_type_erased_test::test_forward));
return test;
}

View File

@ -0,0 +1,94 @@
// Boost.Range library
//
// Copyright Neil Groves 2014. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/range/adaptor/type_erased.hpp>
#include "type_erased_test.hpp"
#include <boost/test/unit_test.hpp>
#include <vector>
namespace boost_range_adaptor_type_erased_test
{
namespace
{
template<
class Traversal
, class ValueType
, class SourceValueType
, class SourceReference
, class TargetValueType
, class TargetReference
>
void mix_values_impl()
{
typedef std::vector<ValueType> Container;
typedef typename boost::any_range_type_generator<
Container
, SourceValueType
, Traversal
, SourceReference
>::type source_type;
typedef typename boost::any_range_type_generator<
Container
, TargetValueType
, Traversal
, TargetReference
>::type target_type;
Container test_data;
for (int i = 0; i < 10; ++i)
test_data.push_back(i);
const source_type source_data(test_data);
target_type t1(source_data);
BOOST_CHECK_EQUAL_COLLECTIONS(source_data.begin(), source_data.end(),
t1.begin(), t1.end());
target_type t2;
t2 = source_data;
BOOST_CHECK_EQUAL_COLLECTIONS(source_data.begin(), source_data.end(),
t2.begin(), t2.end());
}
template<class Traversal>
void mix_values_driver()
{
mix_values_impl<
Traversal,
MockType,
MockType2, const MockType&,
MockType, const MockType&
>();
}
void mix_values()
{
mix_values_driver<boost::single_pass_traversal_tag >();
mix_values_driver<boost::forward_traversal_tag >();
mix_values_driver<boost::bidirectional_traversal_tag >();
mix_values_driver<boost::random_access_traversal_tag >();
}
} // anonymous namespace
} // namespace boost_range_adaptor_type_erased_test
boost::unit_test::test_suite*
init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_mix_values");
test->add(BOOST_TEST_CASE(
&boost_range_adaptor_type_erased_test::mix_values));
return test;
}

View File

@ -0,0 +1,50 @@
// Boost.Range library
//
// Copyright Neil Groves 2014. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/range/adaptor/type_erased.hpp>
#include "type_erased_test.hpp"
#include <boost/test/unit_test.hpp>
#include <deque>
#include <vector>
namespace boost_range_adaptor_type_erased_test
{
namespace
{
void test_random_access()
{
test_type_erased_exercise_buffer_types<
std::deque<int>, boost::random_access_traversal_tag >();
test_type_erased_exercise_buffer_types<
std::vector<int>, boost::random_access_traversal_tag >();
test_type_erased_exercise_buffer_types<
std::deque<MockType>, boost::random_access_traversal_tag >();
test_type_erased_exercise_buffer_types<
std::vector<MockType>, boost::random_access_traversal_tag >();
}
} // anonymous namespace
} // namespace boost_range_adaptor_type_erased_test
boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_random_access");
test->add(BOOST_TEST_CASE(
&boost_range_adaptor_type_erased_test::test_random_access));
return test;
}

View File

@ -0,0 +1,57 @@
// 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)
//
#include <boost/range/adaptor/type_erased.hpp>
#include "type_erased_test.hpp"
#include <boost/test/unit_test.hpp>
#include <deque>
#include <list>
#include <vector>
namespace boost_range_adaptor_type_erased_test
{
namespace
{
void test_single_pass()
{
test_type_erased_exercise_buffer_types<
std::list<int>, boost::single_pass_traversal_tag>();
test_type_erased_exercise_buffer_types<
std::deque<int>, boost::single_pass_traversal_tag>();
test_type_erased_exercise_buffer_types<
std::vector<int>, boost::single_pass_traversal_tag>();
test_type_erased_exercise_buffer_types<
std::list<MockType>, boost::single_pass_traversal_tag>();
test_type_erased_exercise_buffer_types<
std::deque<MockType>, boost::single_pass_traversal_tag>();
test_type_erased_exercise_buffer_types<
std::vector<MockType>, boost::single_pass_traversal_tag>();
}
} // anonymous namespace
} // namespace boost_range_adaptor_type_erased_test
boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_single_pass");
test->add(BOOST_TEST_CASE(
&boost_range_adaptor_type_erased_test::test_single_pass));
return test;
}

View File

@ -0,0 +1,289 @@
// 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)
//
#ifndef BOOST_RANGE_ADAPTOR_TEST_TYPE_ERASED_TEST_HPP
#define BOOST_RANGE_ADAPTOR_TEST_TYPE_ERASED_TEST_HPP
#include <boost/range/algorithm/fill.hpp>
#include <boost/range/algorithm_ext/push_back.hpp>
#include <boost/assign.hpp>
#include <boost/test/test_tools.hpp>
namespace boost_range_adaptor_type_erased_test
{
class MockType
{
public:
MockType()
: m_x(0)
{
}
MockType(boost::int32_t x)
: m_x(x)
{
}
boost::int32_t get() const { return m_x; }
inline bool operator==(const MockType& other) const
{
return m_x == other.m_x;
}
inline bool operator!=(const MockType& other) const
{
return m_x != other.m_x;
}
private:
boost::int32_t m_x;
};
class MockType2 : public MockType
{
public:
MockType2() {}
MockType2(boost::int32_t x) : MockType(x) { }
MockType2(const MockType& other) : MockType(other) { }
};
inline std::ostream& operator<<(std::ostream& out, const MockType& obj)
{
out << obj.get();
return out;
}
template<class Container>
void test_type_erased_impl(Container& c)
{
using namespace boost::adaptors;
typedef typename boost::range_value<Container>::type value_type;
typedef typename boost::adaptors::type_erased<> type_erased_t;
std::vector<value_type> output;
boost::push_back(output, boost::adaptors::type_erase(c, type_erased_t()));
BOOST_CHECK_EQUAL_COLLECTIONS( output.begin(), output.end(),
c.begin(), c.end() );
output.clear();
boost::push_back(output, c | type_erased_t());
BOOST_CHECK_EQUAL_COLLECTIONS( output.begin(), output.end(),
c.begin(), c.end() );
}
template<class Container>
void test_const_and_mutable(Container& c)
{
test_type_erased_impl(c);
const Container& const_c = c;
test_type_erased_impl(const_c);
}
template<class Container>
void test_driver()
{
using namespace boost::assign;
typedef typename boost::range_value<Container>::type value_type;
Container c;
test_const_and_mutable(c);
c += value_type(1);
test_const_and_mutable(c);
c += value_type(2);
test_const_and_mutable(c);
}
template<
class Traversal
, class Container
>
void test_writeable(Container&, boost::single_pass_traversal_tag)
{}
template<
class Traversal
, class Container
>
void test_writeable(Container& source, boost::forward_traversal_tag)
{
using namespace boost::adaptors;
typedef typename boost::range_value<Container>::type value_type;
typedef typename boost::range_difference<Container>::type difference_type;
typedef typename boost::range_reference<Container>::type mutable_reference_type;
typedef boost::any_range<
value_type
, Traversal
, mutable_reference_type
, difference_type
> mutable_any_range;
mutable_any_range r = source | boost::adaptors::type_erased<>();
std::vector<value_type> output_test;
boost::fill(r, value_type(1));
BOOST_CHECK_EQUAL( boost::distance(r), boost::distance(source) );
std::vector<value_type> reference_output(source.size(), value_type(1));
BOOST_CHECK_EQUAL_COLLECTIONS( reference_output.begin(), reference_output.end(),
r.begin(), r.end() );
}
template<
class Container
, class Traversal
, class Buffer
>
void test_type_erased_impl()
{
using namespace boost::adaptors;
typedef typename boost::range_value<Container>::type value_type;
typedef typename boost::any_range_type_generator<
Container
, boost::use_default
, Traversal
, boost::use_default
, boost::use_default
, Buffer
>::type mutable_any_range;
typedef typename boost::any_range_type_generator<
const Container
, boost::use_default
, Traversal
, boost::use_default
, boost::use_default
, Buffer
>::type const_any_range;
typedef boost::adaptors::type_erased<
boost::use_default
, Traversal
, boost::use_default
, boost::use_default
, Buffer
> type_erased_t;
Container source;
for (int i = 0; i < 10; ++i)
source.push_back(value_type(i));
mutable_any_range r(source);
BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
r.begin(), r.end() );
r = mutable_any_range();
BOOST_CHECK_EQUAL( r.empty(), true );
r = source | type_erased_t();
BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
r.begin(), r.end() );
r = mutable_any_range();
r = boost::adaptors::type_erase(source, type_erased_t());
BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
r.begin(), r.end() );
r = mutable_any_range();
test_writeable<Traversal>(source, Traversal());
// convert and construct a const any_range from a mutable source
// range
const_any_range cr(source);
BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
cr.begin(), cr.end() );
// assign an empty range and ensure that this correctly results
// in an empty range. This is important for the validity of
// the rest of the tests.
cr = const_any_range();
BOOST_CHECK_EQUAL( cr.empty(), true );
// Test the pipe type_erased adaptor from a constant source
// range to a constant any_range
const Container& const_source = source;
cr = const_any_range();
cr = const_source | type_erased_t();
BOOST_CHECK_EQUAL_COLLECTIONS( const_source.begin(), const_source.end(),
cr.begin(), cr.end() );
// Test the pipe type erased adaptor from a mutable source
// range to a constant any_range
cr = const_any_range();
cr = source | type_erased_t();
BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
cr.begin(), cr.end() );
// Use the function form of the type_erase adaptor from a constant
// source range
cr = const_any_range();
cr = boost::adaptors::type_erase(const_source, type_erased_t());
BOOST_CHECK_EQUAL_COLLECTIONS( const_source.begin(), const_source.end(),
cr.begin(), cr.end() );
// Assignment from mutable to const...
cr = const_any_range();
cr = r;
BOOST_CHECK_EQUAL_COLLECTIONS( cr.begin(), cr.end(),
r.begin(), r.end() );
// Converting copy from mutable to const...
cr = const_any_range();
cr = const_any_range(r);
BOOST_CHECK_EQUAL_COLLECTIONS( cr.begin(), cr.end(),
r.begin(), r.end() );
}
template<
class Container
, class Traversal
, class Buffer
>
class test_type_erased_impl_fn
{
public:
typedef void result_type;
void operator()()
{
test_type_erased_impl< Container, Traversal, Buffer >();
}
};
template<
class Container
, class Traversal
>
void test_type_erased_exercise_buffer_types()
{
using boost::any_iterator_default_buffer;
using boost::any_iterator_buffer;
using boost::any_iterator_heap_only_buffer;
using boost::any_iterator_stack_only_buffer;
test_type_erased_impl_fn< Container, Traversal, any_iterator_default_buffer >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_heap_only_buffer >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<1> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<2> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<32> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<64> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<128> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_stack_only_buffer<128> >()();
}
} // namespace boost_range_adaptor_type_erased_test
#endif // include guard

View File

@ -0,0 +1,74 @@
// Boost.Range library
//
// Copyright Neil Groves 2014. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/range/adaptor/type_erased.hpp>
#include "type_erased_test.hpp"
#include <boost/test/unit_test.hpp>
#include <algorithm>
#include <vector>
namespace boost_range_adaptor_type_erased_test
{
namespace
{
void template_parameter_conversion()
{
typedef boost::any_range<
int
, boost::random_access_traversal_tag
, int&
, std::ptrdiff_t
> source_range_type;
typedef boost::any_range<
int
, boost::single_pass_traversal_tag
, const int&
, std::ptrdiff_t
> target_range_type;
source_range_type source;
// Converting via construction
target_range_type t1(source);
// Converting via assignment
target_range_type t2;
t2 = source;
// Converting via construction to a type with a reference type
// that is a value
typedef boost::any_range<
int
, boost::single_pass_traversal_tag
, int
, std::ptrdiff_t
> target_range2_type;
target_range2_type t3(source);
target_range2_type t4;
t4 = source;
}
} // anonymous namespace
} // namespace boost_range_adaptor_type_erased_test
boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_tparam_conv");
test->add(BOOST_TEST_CASE(
&boost_range_adaptor_type_erased_test::template_parameter_conversion));
return test;
}

View File

@ -9,6 +9,10 @@
// For more information, see http://www.boost.org/libs/range/
//
#include <boost/range/adaptor/uniqued.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/unique_copy.hpp>
#include <boost/range/algorithm_ext/push_back.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
@ -74,9 +78,82 @@ namespace boost
uniqued_test_impl< std::set< int > >();
uniqued_test_impl< std::multiset< int > >();
}
class istring
{
public:
istring()
: m_value("")
{
}
explicit istring(const char* value)
: m_value(value)
{
}
bool operator==(istring r) const
{
return boost::iequals(m_value, r.m_value);
}
bool operator!=(istring r) const
{
return !operator==(r);
}
inline friend std::ostream& operator<<(std::ostream& out, istring o)
{
return out << o.m_value;
}
const char* get() const { return m_value; }
private:
const char* m_value;
};
struct istring_to_string
{
typedef std::string result_type;
std::string operator()(istring s) const
{
return s.get();
}
};
// This is based on a test-case provided by Eric Neibler.
void uniqued_return_first()
{
using namespace boost::adaptors;
std::vector<istring> strs;
strs.push_back(istring("hello"));
strs.push_back(istring("hElLo"));
strs.push_back(istring("HELLO"));
strs.push_back(istring("ZZZZ"));
std::vector<istring> output1;
boost::unique_copy(strs, std::back_inserter(output1));
std::vector<istring> output2;
boost::push_back(output2, strs | uniqued);
std::vector<std::string> test1;
boost::push_back(test1, output1 | transformed(istring_to_string()));
std::vector<std::string> test2;
boost::push_back(test2, output2 | transformed(istring_to_string()));
BOOST_CHECK_EQUAL_COLLECTIONS(test1.begin(), test1.end(),
test2.begin(), test2.end());
}
} // anonymous namespace
} // namespace boost
boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
@ -85,5 +162,7 @@ init_unit_test_suite(int argc, char* argv[])
test->add( BOOST_TEST_CASE( &boost::uniqued_test ) );
test->add(BOOST_TEST_CASE(&boost::uniqued_return_first));
return test;
}

View File

@ -107,11 +107,14 @@ template<typename Rng>
void test_random_algorithms(Rng & rng, std::random_access_iterator_tag)
{
typedef BOOST_DEDUCED_TYPENAME boost::range_iterator<Rng>::type iterator;
typedef BOOST_DEDUCED_TYPENAME boost::range_value<Rng>::type value_type;
typedef BOOST_DEDUCED_TYPENAME boost::range_size<Rng>::type size_type BOOST_RANGE_UNUSED;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_category<iterator>::type iterator_category;
typedef BOOST_DEDUCED_TYPENAME boost::range_size<Rng>::type
size_type BOOST_RANGE_UNUSED;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_category<iterator>::type
iterator_category BOOST_RANGE_UNUSED;
// just make sure these compile (for now)
if(0)

View File

@ -28,7 +28,9 @@ namespace boost
void test(Container1& cont1, Container2& cont2)
{
typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t;
typedef BOOST_DEDUCED_TYPENAME std::vector<value_t>::iterator iterator_t;
typedef BOOST_DEDUCED_TYPENAME std::vector<value_t>::iterator
iterator_t BOOST_RANGE_UNUSED;
std::vector<value_t> reference_target(cont1.begin(), cont1.end());
reference_target.insert(reference_target.end(),
@ -74,7 +76,8 @@ namespace boost
void test_pred(Container1 cont1, Container2 cont2, BinaryPredicate pred)
{
typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t;
typedef BOOST_DEDUCED_TYPENAME std::vector<value_t>::iterator iterator_t;
typedef BOOST_DEDUCED_TYPENAME std::vector<value_t>::iterator
iterator_t BOOST_RANGE_UNUSED;
sort_container(cont1, pred);
sort_container(cont2, pred);

View File

@ -106,8 +106,11 @@ namespace boost_range_test_algorithm_max_element
{
using namespace boost::assign;
typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t;
typedef BOOST_DEDUCED_TYPENAME boost::remove_const<Container>::type container_t;
typedef BOOST_DEDUCED_TYPENAME Container::value_type
value_t BOOST_RANGE_UNUSED;
typedef BOOST_DEDUCED_TYPENAME boost::remove_const<Container>::type
container_t;
boost::range_test::range_return_test_driver test_driver;

View File

@ -104,8 +104,11 @@ namespace boost_range_test_algorithm_min_element
{
using namespace boost::assign;
typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t;
typedef BOOST_DEDUCED_TYPENAME boost::remove_const<Container>::type container_t;
typedef BOOST_DEDUCED_TYPENAME Container::value_type
value_t BOOST_RANGE_UNUSED;
typedef BOOST_DEDUCED_TYPENAME boost::remove_const<Container>::type
container_t;
boost::range_test::range_return_test_driver test_driver;

View File

@ -160,15 +160,17 @@ namespace boost
MutableContainer2 cont2;
const Container2& cref_cont2 = cont2;
typedef BOOST_DEDUCED_TYPENAME Container1::iterator iterator1_t;
typedef BOOST_DEDUCED_TYPENAME Container1::const_iterator const_iterator1_t;
typedef BOOST_DEDUCED_TYPENAME Container2::iterator iterator2_t;
typedef BOOST_DEDUCED_TYPENAME Container2::const_iterator const_iterator2_t;
typedef BOOST_DEDUCED_TYPENAME Container1::iterator
iterator1_t BOOST_RANGE_UNUSED;
typedef std::pair<iterator1_t, iterator2_t> pair_mmit_t;
typedef std::pair<const_iterator1_t, iterator2_t> pair_cmit_t;
typedef std::pair<iterator1_t, const_iterator2_t> pair_mcit_t;
typedef std::pair<const_iterator1_t, const_iterator2_t> pair_ccit_t;
typedef BOOST_DEDUCED_TYPENAME Container1::const_iterator
const_iterator1_t BOOST_RANGE_UNUSED;
typedef BOOST_DEDUCED_TYPENAME Container2::iterator
iterator2_t BOOST_RANGE_UNUSED;
typedef BOOST_DEDUCED_TYPENAME Container2::const_iterator
const_iterator2_t BOOST_RANGE_UNUSED;
eval_mismatch(cont1, cont2, cont1.end(), cont2.end());
eval_mismatch(cont1, cont2, std::equal_to<int>(), cont1.end(), cont2.end());

View File

@ -90,7 +90,8 @@ namespace boost
template<class Container>
void test_random_shuffle_nogen_impl(Container& cont)
{
typedef BOOST_DEDUCED_TYPENAME range_iterator<Container>::type iterator_t;
typedef BOOST_DEDUCED_TYPENAME range_iterator<Container>::type
iterator_t BOOST_RANGE_UNUSED;
const int MAX_RETRIES = 10000;

View File

@ -36,7 +36,8 @@ namespace
typedef typename boost::range_value<Container>::type value_type;
std::vector<value_type> reference;
typedef BOOST_DEDUCED_TYPENAME std::vector<value_type>::iterator iterator_t;
typedef BOOST_DEDUCED_TYPENAME std::vector<value_type>::iterator
iterator_t BOOST_RANGE_UNUSED;
test_append(
std::remove_copy(c.begin(), c.end(),

View File

@ -38,7 +38,8 @@ namespace
typedef typename boost::range_value<Container>::type value_type;
std::vector<value_type> reference;
typedef BOOST_DEDUCED_TYPENAME std::vector<value_type>::iterator iterator_t;
typedef BOOST_DEDUCED_TYPENAME std::vector<value_type>::iterator
iterator_t BOOST_RANGE_UNUSED;
test_append(
std::replace_copy(c.begin(), c.end(),

View File

@ -31,11 +31,14 @@ namespace
template<class Container, class Iterator>
void test_rotate_copy_impl(Container& cont, Iterator where_it)
{
typedef BOOST_DEDUCED_TYPENAME boost::range_value<Container>::type value_type;
typedef BOOST_DEDUCED_TYPENAME boost::range_value<Container>::type
value_type;
std::vector<value_type> reference;
std::vector<value_type> test;
typedef BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type iterator_t;
typedef BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type
iterator_t BOOST_RANGE_UNUSED;
test_append(
std::rotate_copy(cont.begin(), where_it, cont.end(),

View File

@ -60,7 +60,9 @@ namespace
Integer count, const Value& value,
BinaryPredicate pred)
{
typedef typename std::iterator_traits<ForwardIterator>::iterator_category cat_t;
typedef typename std::iterator_traits<
ForwardIterator
>::iterator_category cat_t BOOST_RANGE_UNUSED;
if (count <= 0)
return first;

View File

@ -10,6 +10,7 @@
#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>
#include <boost/concept_check.hpp>
#include <boost/config.hpp>
enum Container {};
@ -51,6 +52,7 @@ void compat1()
{
std::vector<int> v;
iterator_of< std::vector<int> >::type i = v.begin();
boost::ignore_unused_variable_warning(i);
}
#include <boost/test/included/unit_test.hpp>

View File

@ -11,6 +11,7 @@
// Disable a warning from <xutility> since this noise might
// stop us detecting a problem in our code.
#include <boost/range/counting_range.hpp>
#include <boost/range/adaptor/indirected.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
@ -51,6 +52,22 @@ namespace boost
counting_range_test_impl<Container>(-100, 100);
counting_range_test_impl<Container>(50, 55);
}
void counting_range_test_range()
{
std::vector<int> v;
for (int i = 0; i < 10; ++i)
v.push_back(i);
std::vector<std::vector<int>::iterator> x;
push_back(x, counting_range(v));
std::vector<int> t;
push_back(t, x | boost::adaptors::indirected);
BOOST_CHECK_EQUAL_COLLECTIONS(t.begin(), t.end(),
v.begin(), v.end());
}
}
void counting_range_test()

View File

@ -20,6 +20,7 @@
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/static_assert.hpp>
#include <boost/cstdint.hpp>
#include <list>
#include <vector>

View File

@ -63,18 +63,24 @@ void check_iterator_pair()
BOOST_CHECK( boost::begin( pair ) == pair.first );
BOOST_CHECK( boost::end( pair ) == pair.second );
BOOST_CHECK( boost::empty( pair ) == (pair.first == pair.second) );
BOOST_CHECK( boost::size( pair ) == std::distance( pair.first, pair.second ) );
BOOST_CHECK( boost::size( pair ) ==
static_cast<std::size_t>(
std::distance(pair.first, pair.second)) );
BOOST_CHECK( boost::begin( const_pair ) == const_pair.first );
BOOST_CHECK( boost::end( const_pair ) == const_pair.second );
BOOST_CHECK( boost::empty( const_pair ) == (const_pair.first == const_pair.second) );
BOOST_CHECK( boost::size( const_pair ) == std::distance( const_pair.first, const_pair.second ) );
BOOST_CHECK( boost::size( const_pair ) ==
static_cast<std::size_t>(
std::distance(const_pair.first, const_pair.second)) );
BOOST_CHECK( boost::begin( constness_pair ) == constness_pair.first );
BOOST_CHECK( boost::end( constness_pair ) == constness_pair.second );
BOOST_CHECK( boost::empty( constness_pair ) == (constness_pair.first == const_pair.second) );
BOOST_CHECK( boost::size( constness_pair ) == std::distance( constness_pair.first, constness_pair.second ) );
BOOST_CHECK( boost::size( constness_pair ) ==
static_cast<std::size_t>(
std::distance(constness_pair.first,
constness_pair.second)) );
}

View File

@ -0,0 +1,60 @@
// Boost.Range library
//
// Copyright Neil Groves 2014. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see http://www.boost.org/libs/range/
//
#include <boost/detail/workaround.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/functions.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/variant.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
#include <string>
namespace
{
enum E
{
e1, e2, e3
};
void test_variant_report()
{
typedef boost::mpl::vector<
E,
std::string,
boost::iterator_range<std::string::iterator>
>::type args;
typedef boost::make_variant_over<args>::type variant_t;
variant_t v;
std::string s;
v = boost::iterator_range<std::string::iterator>(s.begin(), s.end());
v = e2;
v = std::string();
// Rationale:
// This is cast to const char* to guard against ambiguity in the case
// where std::string::iterator it a char*
v = static_cast<const char*>("");
}
}
boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] )
{
boost::unit_test::test_suite* test =
BOOST_TEST_SUITE("iterator range and variant interoperability");
test->add(BOOST_TEST_CASE(&test_variant_report));
return test;
}

View File

@ -8,7 +8,12 @@
//
// For more information, see http://www.boost.org/libs/range/
//
// Credits:
// Trac 7376 - was raised by Leonid Gershanovich and his sample was used to
// make the test case to cover this condition.
//
#include <boost/range/join.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/foreach.hpp>
#include <boost/test/test_tools.hpp>
@ -274,6 +279,106 @@ namespace boost
boost::push_back(joined, join(v1, v2));
}
namespace trac7376
{
struct base_type
{
explicit base_type(boost::int32_t value)
: value(value)
{
}
virtual boost::int32_t get() const = 0;
boost::int32_t value;
};
struct derived_type1
: base_type
{
derived_type1(boost::int32_t value)
: base_type(value)
{
}
virtual boost::int32_t get() const
{
return value * 2;
}
};
struct derived_type2
: base_type
{
derived_type2(boost::int32_t value)
: base_type(value)
{
}
virtual boost::int32_t get() const
{
return value * 4;
}
};
struct apply_get
{
typedef boost::int32_t result_type;
result_type operator()(const base_type& arg) const
{
return arg.get();
}
};
void test_reference_types()
{
using namespace boost::adaptors;
typedef boost::range_detail::join_iterator<
std::vector<derived_type1>::iterator,
std::vector<derived_type2>::iterator,
const base_type&,
const base_type&
> join_iterator_t;
std::vector<boost::int32_t> reference_output;
std::vector<derived_type1> x;
for (boost::int32_t i = 0; i < 10; ++i)
{
x.push_back(derived_type1(i));
reference_output.push_back(i * 2);
}
std::vector<derived_type2> y;
for (boost::int32_t i = 0; i < 10; ++i)
{
y.push_back(derived_type2(i));
reference_output.push_back(i * 4);
}
join_iterator_t it(
x,
y,
boost::range_detail::join_iterator_begin_tag());
std::vector<boost::int32_t> output;
boost::push_back(
output,
boost::make_iterator_range(
join_iterator_t(
x, y,
boost::range_detail::join_iterator_begin_tag()),
join_iterator_t(
x, y,
boost::range_detail::join_iterator_end_tag()))
| transformed(apply_get()));
BOOST_CHECK_EQUAL_COLLECTIONS(
output.begin(), output.end(),
reference_output.begin(), reference_output.end());
}
} // namespace trac7376
}
}
@ -285,6 +390,7 @@ init_unit_test_suite(int argc, char* argv[])
test->add( BOOST_TEST_CASE( &boost::join_test ) );
test->add( BOOST_TEST_CASE( &boost::test_join_iterator_reference_type_constness_ticket8483 ) );
test->add( BOOST_TEST_CASE( &boost::trac7376::test_reference_types ) );
return test;
}

View File

@ -0,0 +1,48 @@
// Boost.Range library
//
// Copyright Neil Groves 2014. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// For more information, see http://www.boost.org/libs/range/
//
#include <boost/range/adaptor/indirected.hpp>
#include <boost/optional.hpp>
#include <boost/optional/optional_io.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
#include <vector>
namespace boost
{
namespace
{
void test_ticket_5811_indirected_optional()
{
std::vector<boost::optional<int> > v;
std::vector<int> r;
for (int i = 0; i < 10; ++i)
{
v.push_back(i);
r.push_back(i);
}
BOOST_CHECK_EQUAL_COLLECTIONS(r.begin(), r.end(),
v.begin(), v.end());
}
}
}
boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
boost::unit_test::test_suite* test
= BOOST_TEST_SUITE("RangeTestSuite.ticket_5811_indirected_optional");
test->add(BOOST_TEST_CASE(&boost::test_ticket_5811_indirected_optional));
return test;
}

View File

@ -0,0 +1,51 @@
// Boost.Range library
//
// Copyright Neil Groves 2014. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// For more information, see http://www.boost.org/libs/range/
//
#include <boost/range/iterator_range_core.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
#include <string>
namespace boost
{
namespace
{
class str_ref : public boost::iterator_range<const char*>
{
public:
explicit str_ref(const std::string& str)
: boost::iterator_range<const char*>(
str.c_str(), str.c_str() + str.size())
{
}
};
void test_ticket_6715_iterator_range_equality()
{
str_ref a("test");
str_ref b("test");
BOOST_CHECK(a == b);
}
}
}
boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
boost::unit_test::test_suite* test
= BOOST_TEST_SUITE(
"RangeTestSuite.ticket_6715_iterator_range_equality");
test->add(BOOST_TEST_CASE(
&boost::test_ticket_6715_iterator_range_equality));
return test;
}