Reputation: 4078
I am trying to develop smart iterator, but even when I create a naive one it crash when I am using sort with it.
The range for loop worked well, but std::sort does not.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template<typename I>
class it {
public:
it(I i) : i(i){}
using iterator_category = std::random_access_iterator_tag;
using value_type = typename I::value_type;
using difference_type = std::ptrdiff_t;
using pointer = typename I::pointer;
using reference = typename I::reference;
value_type &operator*() {
return *i;
}
it &operator++() {
++i;
return *this;
}
it &operator--() {
--i;
return *this;
}
bool operator!=(it a) {
return a.i != i;
}
it &operator+(std::size_t n) {
i += n;
return *this;
}
it &operator-(std::size_t n) {
i -= n;
return *this;
}
std::ptrdiff_t operator-(it a) {
return i - a.i;
}
bool operator==(it a) {
return a.i == i;
}
bool operator<(it a) {
return i < a.i;
}
private:
I i;
};
int main()
{
std::vector<int> v = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
for(auto e : v)
std::cout << e << " ";
std::cout << std::endl;
std::sort(it<decltype(v.begin())>(v.begin()), it<decltype(v.end())>(v.end()));
for(auto e : v)
std::cout << e << " ";
std::cout << std::endl;
return 0;
}
The crash happen in "clang-code" here (gdb tell me that) :
struct _Iter_less_iter
{
template<typename _Iterator1, typename _Iterator2>
_GLIBCXX14_CONSTEXPR
bool
operator()(_Iterator1 __it1, _Iterator2 __it2) const
{ return *__it1 < *__it2; }
};
It happened when it deferrence it. Do you have an idea?
Upvotes: 0
Views: 89
Reputation: 103713
Your operator+
has the semantics of operator+=
, and your operator-
has the semantics of operator-=
. They should not modify the iterator, but instead create a new iterator with the modified value and return that. Also, they should both accept signed values. In fact, a proper random access iterator should have both sets of operators, so just keep the functions as they are, but change the signatures.
it& operator+=(difference_type n) {
i += n;
return *this;
}
it &operator-=(difference_type n) {
i -= n;
return *this;
}
Then you can implement operator+
and operator-
in terms of those. (note that these return by value, not reference, and are marked const)
it operator+(difference_type n) const {
it result = *this;
result += n;
return result;
}
it operator-(difference_type n) const {
it result = *this;
result -= n;
return result;
}
Upvotes: 2
Reputation: 76370
Don't know for sure what the underlying problem is, but this is definitely wrong:
it &operator+(std::size_t n) {
i += n;
return *this;
}
That operator should return a new iterator, and not modify the one it's called on. Something like this:
it operator+(std::size_t n) {
it temp = *this;
temp.i += n;
return temp;
}
Note that this returns the iterator by value, not by reference.
Same thing for operator-
.
Upvotes: 3