forked from boostorg/range
merge branch develop
This commit is contained in:
@ -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]
|
||||
|
@ -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()`
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -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<
|
||||
strided_iterator<BaseIterator, Category>
|
||||
, BaseIterator
|
||||
, use_default
|
||||
, boost::forward_traversal_tag
|
||||
> super_t;
|
||||
typedef iterator_facade<
|
||||
strided_iterator<BaseIterator, Category>
|
||||
, 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
|
||||
, bidirectional_traversal_tag
|
||||
, 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<
|
||||
strided_iterator<BaseIterator, bidirectional_traversal_tag>
|
||||
, BaseIterator
|
||||
, use_default
|
||||
, bidirectional_traversal_tag
|
||||
> super_t;
|
||||
typedef iterator_facade<
|
||||
strided_iterator<BaseIterator, bidirectional_traversal_tag>
|
||||
, 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<
|
||||
strided_iterator<BaseIterator, random_access_traversal_tag>
|
||||
, BaseIterator
|
||||
, use_default
|
||||
, random_access_traversal_tag
|
||||
>
|
||||
: public iterator_facade<
|
||||
strided_iterator<BaseIterator, random_access_traversal_tag>
|
||||
, 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<
|
||||
strided_iterator<BaseIterator, random_access_traversal_tag>
|
||||
, BaseIterator
|
||||
, use_default
|
||||
, random_access_traversal_tag
|
||||
> super_t;
|
||||
typedef iterator_facade<
|
||||
strided_iterator<BaseIterator, random_access_traversal_tag>
|
||||
, 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
|
||||
>::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,
|
||||
Category
|
||||
>
|
||||
>
|
||||
range_detail::strided_iterator<
|
||||
typename range_iterator<Rng>::type,
|
||||
Category
|
||||
>
|
||||
>
|
||||
{
|
||||
typedef range_detail::strided_iterator<
|
||||
BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type,
|
||||
Category
|
||||
> iter_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>
|
||||
|
@ -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);
|
||||
|
@ -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,8 +28,8 @@ 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 &&
|
||||
"cannot copy from a container to itself" );
|
||||
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;
|
||||
}
|
||||
|
@ -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,8 +28,8 @@ 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 &&
|
||||
"cannot copy from a container to itself" );
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
typename add_const<
|
||||
typename remove_reference<T>::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;
|
||||
};
|
||||
|
@ -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
|
||||
|
66
include/boost/range/detail/has_member_size.hpp
Normal file
66
include/boost/range/detail/has_member_size.hpp
Normal 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
|
@ -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'
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -25,46 +25,46 @@
|
||||
namespace boost
|
||||
{
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
|
||||
|
||||
namespace range_detail_vc7_1
|
||||
{
|
||||
template< typename C, typename Sig = void(C) >
|
||||
struct range_iterator
|
||||
{
|
||||
typedef BOOST_RANGE_DEDUCED_TYPENAME
|
||||
mpl::eval_if_c< is_const<C>::value,
|
||||
range_const_iterator< typename remove_const<C>::type >,
|
||||
range_mutable_iterator<C> >::type type;
|
||||
};
|
||||
|
||||
template< typename C, typename T >
|
||||
struct range_iterator< C, void(T[]) >
|
||||
{
|
||||
typedef T* type;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
namespace range_detail_vc7_1
|
||||
{
|
||||
template< typename C, typename Sig = void(C) >
|
||||
struct range_iterator
|
||||
{
|
||||
typedef BOOST_RANGE_DEDUCED_TYPENAME
|
||||
mpl::eval_if_c< is_const<C>::value,
|
||||
range_const_iterator< typename remove_const<C>::type >,
|
||||
range_mutable_iterator<C> >::type type;
|
||||
};
|
||||
|
||||
template< typename C, typename T >
|
||||
struct range_iterator< C, void(T[]) >
|
||||
{
|
||||
typedef T* type;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template< typename C >
|
||||
struct range_iterator
|
||||
{
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
|
||||
|
||||
typedef BOOST_RANGE_DEDUCED_TYPENAME
|
||||
range_detail_vc7_1::range_iterator<C>::type type;
|
||||
|
||||
#else
|
||||
|
||||
typedef BOOST_RANGE_DEDUCED_TYPENAME
|
||||
range_detail_vc7_1::range_iterator<C>::type type;
|
||||
|
||||
#else
|
||||
|
||||
typedef BOOST_RANGE_DEDUCED_TYPENAME
|
||||
mpl::eval_if_c< is_const<C>::value,
|
||||
typedef BOOST_RANGE_DEDUCED_TYPENAME
|
||||
mpl::eval_if_c< is_const<C>::value,
|
||||
range_const_iterator< typename remove_const<C>::type >,
|
||||
range_mutable_iterator<C> >::type type;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
@ -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 )
|
||||
template<class Iterator>
|
||||
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,138 +487,143 @@ 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)
|
||||
{
|
||||
return boost::equal( l, r );
|
||||
BOOST_RANGE_CONCEPT_ASSERT((
|
||||
boost::SinglePassRangeConcept<const SinglePassRange1>));
|
||||
BOOST_RANGE_CONCEPT_ASSERT((
|
||||
boost::SinglePassRangeConcept<const SinglePassRange2>));
|
||||
return boost::equal(l, 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)
|
||||
{
|
||||
return !boost::equal( l, 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)
|
||||
{
|
||||
return iterator_range_detail::less_than( l, 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)
|
||||
{
|
||||
return iterator_range_detail::less_or_equal_than( l, 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)
|
||||
{
|
||||
return iterator_range_detail::greater_than( l, 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);
|
||||
}
|
||||
|
||||
template< class IteratorT, class ForwardRange >
|
||||
inline bool operator>=( const ForwardRange& l,
|
||||
const iterator_range<IteratorT>& r )
|
||||
{
|
||||
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 -----------------------------------------//
|
||||
|
||||
@ -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 );
|
||||
}
|
||||
|
||||
|
114
include/boost/range/mfc_map.hpp
Normal file
114
include/boost/range/mfc_map.hpp
Normal 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
|
@ -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,89 +26,163 @@
|
||||
#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>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template< class SinglePassRange, class Value >
|
||||
inline Value accumulate( const SinglePassRange& rng, Value init )
|
||||
template<class SinglePassRange, class Value>
|
||||
inline Value accumulate(const SinglePassRange& rng, Value init)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange> ));
|
||||
return std::accumulate( boost::begin(rng), boost::end(rng), init );
|
||||
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 )
|
||||
template<class SinglePassRange, class Value, class BinaryOperation>
|
||||
inline Value accumulate(const SinglePassRange& rng, Value init,
|
||||
BinaryOperation op)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange> ));
|
||||
return std::accumulate( boost::begin(rng), boost::end(rng), init, op );
|
||||
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),
|
||||
boost::begin(rng2), init );
|
||||
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,
|
||||
class SinglePassRange2,
|
||||
class Value,
|
||||
class BinaryOperation1, class BinaryOperation2 >
|
||||
inline Value inner_product( const SinglePassRange1& rng1, const SinglePassRange2& rng2,
|
||||
Value init,
|
||||
BinaryOperation1 op1, BinaryOperation2 op2 )
|
||||
template<
|
||||
class SinglePassRange1,
|
||||
class SinglePassRange2,
|
||||
class Value,
|
||||
class BinaryOperation1,
|
||||
class BinaryOperation2
|
||||
>
|
||||
inline Value inner_product(
|
||||
const SinglePassRange1& rng1,
|
||||
const SinglePassRange2& rng2,
|
||||
Value init,
|
||||
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::begin(rng2), init, op1, op2 );
|
||||
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);
|
||||
}
|
||||
|
||||
template< class SinglePassRange, class OutputIterator >
|
||||
inline OutputIterator partial_sum ( const SinglePassRange& rng,
|
||||
OutputIterator result )
|
||||
template<class SinglePassRange, class OutputIterator>
|
||||
inline OutputIterator partial_sum(const SinglePassRange& rng,
|
||||
OutputIterator result)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange> ));
|
||||
return std::partial_sum( boost::begin(rng), boost::end(rng), result );
|
||||
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,
|
||||
BinaryOperation op )
|
||||
template<class SinglePassRange, class OutputIterator, class BinaryOperation>
|
||||
inline OutputIterator partial_sum(
|
||||
const SinglePassRange& rng,
|
||||
OutputIterator result,
|
||||
BinaryOperation op)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange> ));
|
||||
return std::partial_sum( boost::begin(rng), boost::end(rng), result, op );
|
||||
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,
|
||||
OutputIterator result )
|
||||
template<class SinglePassRange, class OutputIterator>
|
||||
inline OutputIterator adjacent_difference(
|
||||
const SinglePassRange& rng,
|
||||
OutputIterator result)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<const SinglePassRange> ));
|
||||
return std::adjacent_difference( boost::begin(rng), boost::end(rng),
|
||||
result );
|
||||
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,
|
||||
OutputIterator result,
|
||||
BinaryOperation op )
|
||||
template<class SinglePassRange, class OutputIterator, class BinaryOperation>
|
||||
inline OutputIterator adjacent_difference(
|
||||
const SinglePassRange& rng,
|
||||
OutputIterator result,
|
||||
BinaryOperation op)
|
||||
{
|
||||
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<SinglePassRange> ));
|
||||
return std::adjacent_difference( boost::begin(rng), boost::end(rng),
|
||||
result, op );
|
||||
BOOST_RANGE_CONCEPT_ASSERT((
|
||||
SinglePassRangeConcept<const SinglePassRange>));
|
||||
|
||||
return std::adjacent_difference(boost::begin(rng), boost::end(rng),
|
||||
result, op);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
@ -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)) && \
|
||||
|
@ -31,14 +31,18 @@
|
||||
|
||||
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;
|
||||
@ -46,17 +50,25 @@ namespace boost
|
||||
typedef BOOST_DEDUCED_TYPENAME range_difference<ForwardRange>::type difference_type;
|
||||
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) )
|
||||
sub_range( const sub_range& r )
|
||||
: base( static_cast<const base&>( r ) )
|
||||
@ -64,39 +76,57 @@ namespace boost
|
||||
#endif
|
||||
|
||||
template< class ForwardRange2 >
|
||||
sub_range( ForwardRange2& r ) :
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 800 )
|
||||
base( impl::adl_begin( r ), impl::adl_end( r ) )
|
||||
#else
|
||||
base( r )
|
||||
#endif
|
||||
{ }
|
||||
|
||||
template< class ForwardRange2 >
|
||||
sub_range( const 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 ) )
|
||||
#else
|
||||
base( r )
|
||||
#endif
|
||||
#endif
|
||||
{ }
|
||||
|
||||
template< class ForwardRange2 >
|
||||
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 ) )
|
||||
#else
|
||||
base( r )
|
||||
#endif
|
||||
{ }
|
||||
|
||||
template< class Iter >
|
||||
sub_range( Iter first, Iter last ) :
|
||||
base( first, last )
|
||||
{ }
|
||||
|
||||
template< class ForwardRange2 >
|
||||
sub_range& operator=( ForwardRange2& r )
|
||||
|
||||
template<class ForwardRange2>
|
||||
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 )
|
||||
template<class ForwardRange2>
|
||||
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))
|
||||
|
284
test/Jamfile.v2
284
test/Jamfile.v2
@ -13,12 +13,12 @@
|
||||
import testing ;
|
||||
|
||||
project
|
||||
: requirements
|
||||
<library>/boost/test//boost_unit_test_framework/
|
||||
<library>/boost/regex//boost_regex/
|
||||
<link>static
|
||||
<threading>multi
|
||||
;
|
||||
: requirements
|
||||
<library>/boost/test//boost_unit_test_framework/
|
||||
<library>/boost/regex//boost_regex/
|
||||
<link>static
|
||||
<threading>multi
|
||||
;
|
||||
|
||||
rule range-test ( name : includes * )
|
||||
{
|
||||
@ -31,136 +31,150 @@ rule range-test ( name : includes * )
|
||||
}
|
||||
|
||||
test-suite range :
|
||||
[ compile-fail compile_fail/iterator_range1.cpp ]
|
||||
[ range-test adaptor_test/adjacent_filtered ]
|
||||
[ range-test adaptor_test/copied ]
|
||||
[ range-test adaptor_test/filtered ]
|
||||
[ range-test adaptor_test/indexed ]
|
||||
[ range-test adaptor_test/indirected ]
|
||||
[ range-test adaptor_test/map ]
|
||||
[ range-test adaptor_test/replaced ]
|
||||
[ range-test adaptor_test/replaced_if ]
|
||||
[ range-test adaptor_test/reversed ]
|
||||
[ range-test adaptor_test/sliced ]
|
||||
[ range-test adaptor_test/strided ]
|
||||
[ range-test adaptor_test/strided2 ]
|
||||
[ range-test adaptor_test/tokenized ]
|
||||
[ range-test adaptor_test/transformed ]
|
||||
[ range-test adaptor_test/type_erased ]
|
||||
[ range-test adaptor_test/uniqued ]
|
||||
[ range-test adaptor_test/adjacent_filtered_example ]
|
||||
[ range-test adaptor_test/copied_example ]
|
||||
[ range-test adaptor_test/filtered_example ]
|
||||
[ range-test adaptor_test/indexed_example ]
|
||||
[ range-test adaptor_test/indirected_example ]
|
||||
[ range-test adaptor_test/map_keys_example ]
|
||||
[ range-test adaptor_test/map_values_example ]
|
||||
[ range-test adaptor_test/replaced_example ]
|
||||
[ range-test adaptor_test/replaced_if_example ]
|
||||
[ range-test adaptor_test/reversed_example ]
|
||||
[ range-test adaptor_test/sliced_example ]
|
||||
[ range-test adaptor_test/strided_example ]
|
||||
[ range-test adaptor_test/transformed_example ]
|
||||
[ range-test adaptor_test/tokenized_example ]
|
||||
[ range-test adaptor_test/type_erased_example ]
|
||||
[ range-test adaptor_test/uniqued_example ]
|
||||
[ range-test algorithm_test/adjacent_find ]
|
||||
[ range-test algorithm_test/binary_search ]
|
||||
[ range-test algorithm_test/copy ]
|
||||
[ range-test algorithm_test/copy_backward ]
|
||||
[ range-test algorithm_test/count ]
|
||||
[ range-test algorithm_test/count_if ]
|
||||
[ range-test algorithm_test/equal ]
|
||||
[ range-test algorithm_test/equal_range ]
|
||||
[ range-test algorithm_test/fill ]
|
||||
[ range-test algorithm_test/find ]
|
||||
[ range-test algorithm_test/find_if ]
|
||||
[ range-test algorithm_test/find_end ]
|
||||
[ range-test algorithm_test/find_first_of ]
|
||||
[ range-test algorithm_test/for_each ]
|
||||
[ range-test algorithm_test/generate ]
|
||||
[ range-test algorithm_test/heap ]
|
||||
[ range-test algorithm_test/includes ]
|
||||
[ range-test algorithm_test/inplace_merge ]
|
||||
[ range-test algorithm_test/lexicographical_compare ]
|
||||
[ range-test algorithm_test/lower_bound ]
|
||||
[ range-test algorithm_test/max_element ]
|
||||
[ range-test algorithm_test/merge ]
|
||||
[ range-test algorithm_test/min_element ]
|
||||
[ range-test algorithm_test/mismatch ]
|
||||
[ range-test algorithm_test/next_permutation ]
|
||||
[ range-test algorithm_test/nth_element ]
|
||||
[ range-test algorithm_test/partial_sort ]
|
||||
[ range-test algorithm_test/partition ]
|
||||
[ range-test algorithm_test/prev_permutation ]
|
||||
[ range-test algorithm_test/random_shuffle ]
|
||||
[ range-test algorithm_test/remove ]
|
||||
[ range-test algorithm_test/remove_copy ]
|
||||
[ range-test algorithm_test/remove_copy_if ]
|
||||
[ range-test algorithm_test/remove_if ]
|
||||
[ range-test algorithm_test/replace ]
|
||||
[ range-test algorithm_test/replace_copy ]
|
||||
[ range-test algorithm_test/replace_copy_if ]
|
||||
[ range-test algorithm_test/replace_if ]
|
||||
[ range-test algorithm_test/reverse ]
|
||||
[ range-test algorithm_test/reverse_copy ]
|
||||
[ range-test algorithm_test/rotate ]
|
||||
[ range-test algorithm_test/rotate_copy ]
|
||||
[ range-test algorithm_test/search ]
|
||||
[ range-test algorithm_test/search_n ]
|
||||
[ range-test algorithm_test/set_difference ]
|
||||
[ range-test algorithm_test/set_intersection ]
|
||||
[ range-test algorithm_test/set_symmetric_difference ]
|
||||
[ range-test algorithm_test/set_union ]
|
||||
[ range-test algorithm_test/sort ]
|
||||
[ range-test algorithm_test/stable_partition ]
|
||||
[ range-test algorithm_test/stable_sort ]
|
||||
[ range-test algorithm_test/swap_ranges ]
|
||||
[ range-test algorithm_test/transform ]
|
||||
[ range-test algorithm_test/unique ]
|
||||
[ range-test algorithm_test/unique_copy ]
|
||||
[ range-test algorithm_test/upper_bound ]
|
||||
[ range-test algorithm_ext_test/copy_n ]
|
||||
[ range-test algorithm_ext_test/erase ]
|
||||
[ range-test algorithm_ext_test/for_each_ext ]
|
||||
[ range-test algorithm_ext_test/insert ]
|
||||
[ range-test algorithm_ext_test/iota ]
|
||||
[ range-test algorithm_ext_test/is_sorted ]
|
||||
[ range-test algorithm_ext_test/overwrite ]
|
||||
[ range-test algorithm_ext_test/push_back ]
|
||||
[ range-test algorithm_ext_test/push_front ]
|
||||
[ range-test adl_conformance ]
|
||||
[ range-test adl_conformance_no_using ]
|
||||
[ range-test algorithm ]
|
||||
[ range-test algorithm_example ]
|
||||
[ range-test array ]
|
||||
# [ range-test atl : <include>$(VC71_ROOT)/atlmfc/include ]
|
||||
[ compile-fail compile_fail/iterator_range1.cpp ]
|
||||
[ range-test adaptor_test/adjacent_filtered ]
|
||||
[ range-test adaptor_test/copied ]
|
||||
[ range-test adaptor_test/filtered ]
|
||||
[ range-test adaptor_test/indexed ]
|
||||
[ range-test adaptor_test/indirected ]
|
||||
[ range-test adaptor_test/map ]
|
||||
[ range-test adaptor_test/replaced ]
|
||||
[ range-test adaptor_test/replaced_if ]
|
||||
[ range-test adaptor_test/reversed ]
|
||||
[ 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 ]
|
||||
[ range-test adaptor_test/filtered_example ]
|
||||
[ range-test adaptor_test/indexed_example ]
|
||||
[ range-test adaptor_test/indirected_example ]
|
||||
[ range-test adaptor_test/map_keys_example ]
|
||||
[ range-test adaptor_test/map_values_example ]
|
||||
[ range-test adaptor_test/replaced_example ]
|
||||
[ range-test adaptor_test/replaced_if_example ]
|
||||
[ range-test adaptor_test/reversed_example ]
|
||||
[ range-test adaptor_test/sliced_example ]
|
||||
[ range-test adaptor_test/strided_example ]
|
||||
[ range-test adaptor_test/transformed_example ]
|
||||
[ range-test adaptor_test/tokenized_example ]
|
||||
[ range-test adaptor_test/type_erased_example ]
|
||||
[ range-test adaptor_test/uniqued_example ]
|
||||
[ range-test algorithm_test/adjacent_find ]
|
||||
[ range-test algorithm_test/binary_search ]
|
||||
[ range-test algorithm_test/copy ]
|
||||
[ range-test algorithm_test/copy_backward ]
|
||||
[ range-test algorithm_test/count ]
|
||||
[ range-test algorithm_test/count_if ]
|
||||
[ range-test algorithm_test/equal ]
|
||||
[ range-test algorithm_test/equal_range ]
|
||||
[ range-test algorithm_test/fill ]
|
||||
[ range-test algorithm_test/find ]
|
||||
[ range-test algorithm_test/find_if ]
|
||||
[ range-test algorithm_test/find_end ]
|
||||
[ range-test algorithm_test/find_first_of ]
|
||||
[ range-test algorithm_test/for_each ]
|
||||
[ range-test algorithm_test/generate ]
|
||||
[ range-test algorithm_test/heap ]
|
||||
[ range-test algorithm_test/includes ]
|
||||
[ range-test algorithm_test/inplace_merge ]
|
||||
[ range-test algorithm_test/lexicographical_compare ]
|
||||
[ range-test algorithm_test/lower_bound ]
|
||||
[ range-test algorithm_test/max_element ]
|
||||
[ range-test algorithm_test/merge ]
|
||||
[ range-test algorithm_test/min_element ]
|
||||
[ range-test algorithm_test/mismatch ]
|
||||
[ range-test algorithm_test/next_permutation ]
|
||||
[ range-test algorithm_test/nth_element ]
|
||||
[ range-test algorithm_test/partial_sort ]
|
||||
[ range-test algorithm_test/partition ]
|
||||
[ range-test algorithm_test/prev_permutation ]
|
||||
[ range-test algorithm_test/random_shuffle ]
|
||||
[ range-test algorithm_test/remove ]
|
||||
[ range-test algorithm_test/remove_copy ]
|
||||
[ range-test algorithm_test/remove_copy_if ]
|
||||
[ range-test algorithm_test/remove_if ]
|
||||
[ range-test algorithm_test/replace ]
|
||||
[ range-test algorithm_test/replace_copy ]
|
||||
[ range-test algorithm_test/replace_copy_if ]
|
||||
[ range-test algorithm_test/replace_if ]
|
||||
[ range-test algorithm_test/reverse ]
|
||||
[ range-test algorithm_test/reverse_copy ]
|
||||
[ range-test algorithm_test/rotate ]
|
||||
[ range-test algorithm_test/rotate_copy ]
|
||||
[ range-test algorithm_test/search ]
|
||||
[ range-test algorithm_test/search_n ]
|
||||
[ range-test algorithm_test/set_difference ]
|
||||
[ range-test algorithm_test/set_intersection ]
|
||||
[ range-test algorithm_test/set_symmetric_difference ]
|
||||
[ range-test algorithm_test/set_union ]
|
||||
[ range-test algorithm_test/sort ]
|
||||
[ range-test algorithm_test/stable_partition ]
|
||||
[ range-test algorithm_test/stable_sort ]
|
||||
[ range-test algorithm_test/swap_ranges ]
|
||||
[ range-test algorithm_test/transform ]
|
||||
[ range-test algorithm_test/unique ]
|
||||
[ range-test algorithm_test/unique_copy ]
|
||||
[ range-test algorithm_test/upper_bound ]
|
||||
[ range-test algorithm_ext_test/copy_n ]
|
||||
[ range-test algorithm_ext_test/erase ]
|
||||
[ range-test algorithm_ext_test/for_each_ext ]
|
||||
[ range-test algorithm_ext_test/insert ]
|
||||
[ range-test algorithm_ext_test/iota ]
|
||||
[ range-test algorithm_ext_test/is_sorted ]
|
||||
[ range-test algorithm_ext_test/overwrite ]
|
||||
[ range-test algorithm_ext_test/push_back ]
|
||||
[ range-test algorithm_ext_test/push_front ]
|
||||
[ range-test adl_conformance ]
|
||||
[ range-test adl_conformance_no_using ]
|
||||
[ range-test algorithm ]
|
||||
[ range-test algorithm_example ]
|
||||
[ range-test array ]
|
||||
# [ range-test atl : <include>$(VC71_ROOT)/atlmfc/include ]
|
||||
[ range-test begin ]
|
||||
[ range-test combine ]
|
||||
[ range-test compat2 ]
|
||||
[ range-test compat3 ]
|
||||
[ range-test const_ranges ]
|
||||
[ range-test counting_range ]
|
||||
[ range-test end ]
|
||||
[ range-test extension_mechanism ]
|
||||
[ range-test extension_size ]
|
||||
[ range-test has_range_iterator ]
|
||||
[ range-test irange ]
|
||||
[ range-test istream_range ]
|
||||
[ range-test iterator_pair ]
|
||||
[ range-test iterator_range ]
|
||||
# [ range-test mfc : <include>$(VC71_ROOT)/atlmfc/include ]
|
||||
[ range-test combine ]
|
||||
[ range-test compat2 ]
|
||||
[ range-test compat3 ]
|
||||
[ range-test const_ranges ]
|
||||
[ range-test counting_range ]
|
||||
[ range-test end ]
|
||||
[ range-test extension_mechanism ]
|
||||
[ range-test extension_size ]
|
||||
[ range-test has_range_iterator ]
|
||||
[ range-test irange ]
|
||||
[ 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 ]
|
||||
[ range-test pointer_as_iterator ]
|
||||
[ range-test reversible_range ]
|
||||
[ range-test std_container ]
|
||||
[ range-test string ]
|
||||
[ range-test sub_range ]
|
||||
[ range-test ticket_5486 ]
|
||||
[ range-test ticket_5544_terminate_irange ]
|
||||
[ range-test ticket_5547 ]
|
||||
[ range-test ticket_5556_is_sorted_namespace ]
|
||||
[ range-test ticket_6944 ]
|
||||
[ range-test partial_workaround ]
|
||||
[ range-test pointer_as_iterator ]
|
||||
[ range-test reversible_range ]
|
||||
[ range-test std_container ]
|
||||
[ range-test string ]
|
||||
[ range-test sub_range ]
|
||||
[ range-test ticket_5486 ]
|
||||
[ 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 ]
|
||||
;
|
||||
|
||||
|
@ -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> >();
|
||||
}
|
||||
|
||||
|
69
test/adaptor_test/ticket_6742_transformed_c4789_warning.cpp
Normal file
69
test/adaptor_test/ticket_6742_transformed_c4789_warning.cpp
Normal 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;
|
||||
}
|
56
test/adaptor_test/ticket_8676_sliced_transformed.cpp
Normal file
56
test/adaptor_test/ticket_8676_sliced_transformed.cpp
Normal 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;
|
||||
}
|
67
test/adaptor_test/ticket_9519_strided_reversed.cpp
Normal file
67
test/adaptor_test/ticket_9519_strided_reversed.cpp
Normal 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;
|
||||
}
|
||||
|
@ -6,476 +6,39 @@
|
||||
// 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)
|
||||
{
|
||||
}
|
||||
void test_type_erased()
|
||||
{
|
||||
test_driver< std::list<int> >();
|
||||
test_driver< std::vector<int> >();
|
||||
|
||||
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()
|
||||
{
|
||||
test_driver< std::list<int> >();
|
||||
test_driver< std::vector<int> >();
|
||||
|
||||
test_driver< std::list<MockType> >();
|
||||
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 );
|
||||
}
|
||||
}
|
||||
test_driver< std::list<MockType> >();
|
||||
test_driver< std::vector<MockType> >();
|
||||
}
|
||||
|
||||
} // 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;
|
||||
}
|
||||
|
||||
|
88
test/adaptor_test/type_erased_abstract.cpp
Normal file
88
test/adaptor_test/type_erased_abstract.cpp
Normal 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;
|
||||
}
|
57
test/adaptor_test/type_erased_bidirectional.cpp
Normal file
57
test/adaptor_test/type_erased_bidirectional.cpp
Normal 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;
|
||||
}
|
||||
|
70
test/adaptor_test/type_erased_brackets.cpp
Normal file
70
test/adaptor_test/type_erased_brackets.cpp
Normal 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;
|
||||
}
|
||||
|
57
test/adaptor_test/type_erased_forward.cpp
Normal file
57
test/adaptor_test/type_erased_forward.cpp
Normal 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;
|
||||
}
|
||||
|
94
test/adaptor_test/type_erased_mix_values.cpp
Normal file
94
test/adaptor_test/type_erased_mix_values.cpp
Normal 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;
|
||||
}
|
||||
|
50
test/adaptor_test/type_erased_random_access.cpp
Normal file
50
test/adaptor_test/type_erased_random_access.cpp
Normal 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;
|
||||
}
|
||||
|
57
test/adaptor_test/type_erased_single_pass.cpp
Normal file
57
test/adaptor_test/type_erased_single_pass.cpp
Normal 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;
|
||||
}
|
||||
|
289
test/adaptor_test/type_erased_test.hpp
Normal file
289
test/adaptor_test/type_erased_test.hpp
Normal 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
|
74
test/adaptor_test/type_erased_tparam_conv.cpp
Normal file
74
test/adaptor_test/type_erased_tparam_conv.cpp
Normal 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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -107,12 +107,15 @@ 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_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 BOOST_RANGE_UNUSED;
|
||||
|
||||
// just make sure these compile (for now)
|
||||
if(0)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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()
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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)) );
|
||||
}
|
||||
|
||||
|
||||
|
60
test/iterator_range_variant.cpp
Normal file
60
test/iterator_range_variant.cpp
Normal 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;
|
||||
}
|
106
test/join.cpp
106
test/join.cpp
@ -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;
|
||||
}
|
||||
|
48
test/ticket_5811_indirected_optional.cpp
Normal file
48
test/ticket_5811_indirected_optional.cpp
Normal 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;
|
||||
}
|
51
test/ticket_6715_iterator_range_equality.cpp
Normal file
51
test/ticket_6715_iterator_range_equality.cpp
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user