Issue
I'm making my own vector container and I'm trying to implement an iterator that works like the real one, using the C++98 standard.
This is homework so I don't want the answer just a hint as to where I should look and what I should learn to be able to tackle this problem.
So basically I'm trying to make this code work:
ft::vector<int> v (100, 100);
ft::vector<int>::iterator it = v.begin();
ft::vector<int>::const_iterator cit = it;
std::cout << (cit == it) << std::endl; //comparison 1 /// works
std::cout << (it == cit) << std::endl; //comparison 2 /// doesn't compile
std::cout << (cit + 1 == it + 1) << std::endl; //doesn't work
std::cout << (it + 1 == cit + 1) << std::endl; //doesn't work
iterator and const_iterator are typedefs like this:
typedef typename ft::iterator_vector<value_type> iterator;
typedef typename ft::iterator_vector<const value_type> const_iterator;
And value type being the type passed to the vector template.
The first comparison didn't work until I added a user-defined conversion operator in my iterator template to convert (the other way around actually as pointed out by @TedLyngmo)
which is iterator<const foo> into iterator<foo>operator iterator_vector<const value_type>() const { return _p; }
but the compiler says that I need now to be able to convert a iterator<const foo> into a const iterator<foo> and I have no idea how to proceed.
This is the implementation of my iterator:
template <class T>
class iterator_vector : public ft::iterator<std::random_access_iterator_tag, T> {
public:
typedef ft::iterator<std::random_access_iterator_tag, T> iterator;
typedef ft::iterator_traits<iterator> iterator_traits;
typedef typename iterator_traits::difference_type difference_type;
typedef typename iterator_traits::value_type value_type;
typedef typename iterator_traits::pointer pointer;
typedef typename iterator_traits::reference reference;
typedef typename iterator_traits::iterator_category iterator_category;
/*
** Member functions
*/
iterator_vector(pointer p = 0) : _p(p) {}
~iterator_vector(void) {}
operator iterator_vector<const value_type>() const { return _p; }
iterator_vector& operator++() { ++_p; return *this; }
iterator_vector operator++(int)
{
iterator_vector r = *this;
++_p;
return r;
}
iterator_vector& operator--() { --_p; return *this; }
iterator_vector operator--(int)
{
iterator_vector r = *this;
--_p;
return r;
}
iterator_vector operator+(size_t n) const { return iterator_vector(_p + n); }
iterator_vector operator-(size_t n) const { return iterator_vector(_p - n); }
iterator_vector& operator+=(size_t n) { _p += n; return *this; }
iterator_vector& operator-=(size_t n) { _p -= n; return *this; }
difference_type operator+(iterator_vector rhs) const { return _p + rhs._p; }
difference_type operator-(iterator_vector rhs) const { return _p - rhs._p; }
reference operator*(void) const { return *_p; }
pointer operator->() const { return _p; }
reference operator[](size_t n) const { return _p[n]; }
bool operator==(const iterator_vector& rhs) const { return _p == rhs._p; }
bool operator!=(const iterator_vector& rhs) const { return _p != rhs._p; }
bool operator<(const iterator_vector& rhs) const { return _p > rhs._p; }
bool operator>(const iterator_vector& rhs) const { return _p < rhs._p; }
bool operator<=(const iterator_vector& rhs) const { return _p <= rhs._p; }
bool operator>=(const iterator_vector& rhs) const { return _p >= rhs._p; }
/*
** Non-member functions
*/
friend iterator_vector operator+(size_t n, const iterator_vector& rhs) { return iterator_vector(rhs._p + n); }
friend iterator_vector operator-(size_t n, const iterator_vector& rhs) { return iterator_vector(rhs._p - n); }
private:
pointer _p;
};
Solution
It seems from your comments in your code about what is failing that you are missing a comparison function for when iterator is to the left and the const_iterator is to the right. You could add this free function:
template<typename T>
bool operator==(const iterator_vector<T>& lhs, const iterator_vector<const T>& rhs) {
// just swap the order here and the implicit conversion from `iterator`
// to `const_iterator` from `lhs` solves the rest:
return rhs == lhs;
}
I added a user-defined conversion operator in my iterator template to convert
iterator<const foo>intoiterator<foo>
No, you added an implicit conversion the other way around. That is, from iterator to const_iterator - which is good!
An alternative could be to make the two iterators friends to not have to implement similar swapping lhs with rhs functions for all your operators. The operators in your template would then become:
// define these before your class template (borrowed from C++11):
template< class T > struct remove_const { typedef T type; };
template< class T > struct remove_const<const T> { typedef T type; };
//... in your class template:
friend class iterator_vector<typename remove_const<T>::type>;
friend class iterator_vector<const T>;
template<typename U>
bool operator==(const iterator_vector<U>& rhs) const { return _p == rhs._p; }
template<typename U>
bool operator!=(const iterator_vector<U>& rhs) const { return _p != rhs._p; }
template<typename U>
bool operator<(const iterator_vector<U>& rhs) const { return _p > rhs._p; }
template<typename U>
bool operator>(const iterator_vector<U>& rhs) const { return _p < rhs._p; }
template<typename U>
bool operator<=(const iterator_vector<U>& rhs) const { return _p <= rhs._p; }
template<typename U>
bool operator>=(const iterator_vector<U>& rhs) const { return _p >= rhs._p; }
Answered By - Ted Lyngmo Answer Checked By - Cary Denson (PHPFixing Admin)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.