I'm writing a custom vector class:
#include <iterator>
template <typename T>
class vector {
public:
using value_type = T;
using pointer = value_type*;
using iterator = pointer;
using const_iterator = const iterator;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
auto crbegin() const -> const_reverse_iterator {
return const_reverse_iterator(data_);
}
private:
pointer data_{};
};
int main(int argc, char* argv[]) {
vector<int> v;
auto i = v.crbegin();
return 0;
}
When compiling the code above, I get this error (on GCC and MSVC):
error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<int* const>’
The error goes away when I change the reverse iterator definition to std::reverse_iterator<const T*>
. What's the difference compared to std::reverse_iterator<const_iterator>
?
The problem can be reduced to this:
#include <iterator>
template <typename T>
class vector {
public:
using value_type = T;
using pointer = value_type*;
using const_reverse_iterator = std::reverse_iterator<const pointer>;
auto crbegin() const -> const_reverse_iterator {
return const_reverse_iterator(data_);
}
private:
pointer data_{};
};
int main() {
vector<int> v;
auto i = v.crbegin();
(void) i;
return 0;
}
And the error message from clang makes the nature of the problem clearer:
no type named 'reference' in 'std::iterator_traits<int *const>'
^^^^^^^^^^
And so we see that what you thought was a const *int
(i.e. the pointed-to object is const
) is in fact an int *const
(i.e the pointer itself is const
).
Here's a simple fix:
#include <iterator>
template <typename T>
class vector {
public:
using value_type = T;
using pointer = value_type*;
using const_pointer = const value_type*;
using const_reverse_iterator = std::reverse_iterator<const_pointer>;
auto crbegin() const -> const_reverse_iterator {
return const_reverse_iterator(data_);
}
private:
pointer data_{};
};
int main() {
vector<int> v;
auto i = v.crbegin();
(void) i;
return 0;
}