Opened 10 years ago
Closed 9 years ago
#7824 closed Bugs (fixed)
"++--rng.end() == rng.end()" can fail for strided ranges
| Reported by: | Michel Morin | Owned by: | Neil Groves |
|---|---|---|---|
| Milestone: | To Be Determined | Component: | range |
| Version: | Boost Development Trunk | Severity: | Problem |
| Keywords: | Cc: |
Description
Attached a test case for which "++--rng.end() == rng.end()" fails.
Due to this bug, libc++'s deque<T>::insert function misunderstands
the size of strided ranges. For example,
using boost::strided_range;
using boost::adaptors::strided;
int ar[3] = {0, 1, 2};
strided_range<int[3]> rng = ar | strided(3);
std::deque<int> cont;
cont.insert(cont.begin(), rng.begin(), rng.end());
std::cout << cont.size() << std::endl;
outputs 2 (not 1) with libc++.
You can see libs/range/test/adaptor_test/strided.cpp fails
on test runners with libc++.
Attachments (1)
Change History (3)
by , 10 years ago
| Attachment: | strided_testcase.cpp added |
|---|
comment:1 by , 10 years ago
Just for reference, here is a sample implementation of strided_iterator
for Random Access Range (without zero-stride support),
which can pass strided.cpp test (other than strided_test_zero_stride).
// for Random Access Range (without zero-stride support)
template <typename BaseIterator>
class strided_iterator<BaseIterator, boost::random_access_traversal_tag>
: public iterator_facade<
strided_iterator<BaseIterator, boost::random_access_traversal_tag>
, typename std::iterator_traits<BaseIterator>::value_type
, boost::random_access_traversal_tag
, typename std::iterator_traits<BaseIterator>::reference
, typename std::iterator_traits<BaseIterator>::difference_type
>
{
public:
// types
typedef typename std::iterator_traits<BaseIterator>::reference reference;
typedef typename std::iterator_traits<BaseIterator>::difference_type difference_type;
// ctors
strided_iterator() {}
strided_iterator(
BaseIterator first
, BaseIterator it
, BaseIterator last
, difference_type stride
)
: m_begin(first)
, m_offset((it - first) % stride == 0 ? (it - first) / stride : (it - first) / stride + 1)
, m_stride(stride)
{}
private:
// iterator_facade core operations
friend class boost::iterator_core_access;
reference dereference() const
{ return *(m_begin + m_stride * m_offset); }
bool equal(strided_iterator const& other) const
{ return m_begin == other.m_begin && m_offset == other.m_offset; }
void increment() { ++m_offset; }
void decrement() { --m_offset; }
void advance(difference_type n) { m_offset += n; }
difference_type distance_to(strided_iterator const& other) const
{ return other.m_offset - m_offset; }
// data
BaseIterator m_begin; // the begin iterator of an input range
difference_type m_offset; // the number of strides taken by this iterator
difference_type m_stride;
};
comment:2 by , 9 years ago
| Resolution: | → fixed |
|---|---|
| Status: | new → closed |
Thanks for the report. The posted implementation does fix this problem but would introduce a number of others. I have reimplemented the strided iterators and eliminated this issue.
I apologise for the nuisance this defect has caused you. Thanks for helping.

A test case for which "
++--rng.end() == rng.end()" fails.