Home > OS >  Cannot convert custom iterator to const_iterator
Cannot convert custom iterator to const_iterator

Time:12-13

I am coding an implementation/copy of the std::vector container, and I am having some issues with its iterators.

My random_access_iterator and vector class are implemented like this:

namespace ft
{
    template <typename T>
    class random_access_iterator
    {
        public:
            typedef T value_type;
            typedef value_type* pointer;
            // [...]

        private:
            pointer _ptr;

        public:
            random_access_iterator( void ) : _ptr(pointer()) {}
            random_access_iterator( const random_access_iterator& src ) { *this = src; }
            random_access_iterator& operator= ( const random_access_iterator& src ) { this->_ptr = src._ptr; return *this; }
            // [...]
    };

    template<class T>
    class vector
    {
        public:
            typedef T value_type;
            typedef random_access_iterator<value_type> iterator;
            typedef random_access_iterator<const value_type> const_iterator;
            // [...]

        public:
            vector( void ) {}
            // [...]
    };
}

int main()
{
    ft::vector<int>::iterator it;
    ft::vector<int>::const_iterator cit(it);
    return 0;
}

The Copy Constructor of random_access_iterator<const int> receiving a random_access_iterator<int> in the main function results in a compile-time error:

iterator_test.cpp: In function ‘int main()’:
iterator_test.cpp:39:47: error: no matching function for call to ‘ft::random_access_iterator<const int>::random_access_iterator(ft::vector<int>::iterator&)’
   39 |         ft::vector<int>::const_iterator cit(it);
      |                                               ^
iterator_test.cpp:16:25: note: candidate: ‘ft::random_access_iterator<T>::random_access_iterator(const ft::random_access_iterator<T>&) [with T = const int]’
   16 |                         random_access_iterator( const random_access_iterator& src ) { *this = src; }
      |                         ^~~~~~~~~~~~~~~~~~~~~~
iterator_test.cpp:16:79: note:   no known conversion for argument 1 from ‘ft::vector<int>::iterator’ {aka ‘ft::random_access_iterator<int>’} to ‘const ft::random_access_iterator<const int>&’
   16 |                         random_access_iterator( const random_access_iterator& src ) { *this = src; }
      |                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
iterator_test.cpp:15:25: note: candidate: ‘ft::random_access_iterator<T>::random_access_iterator() [with T = const int]’
   15 |                         random_access_iterator( void ) : _ptr(pointer()) {}
      |                         ^~~~~~~~~~~~~~~~~~~~~~
iterator_test.cpp:15:25: note:   candidate expects 0 arguments, 1 provided

I am using c file.cpp -std=c 98 to compile.

For your information, I am not allowed to use anything newer than C 98. I would be very thankful if any of you could explain to me why this is wrong and what I could do to make it behave like the SDL.

CodePudding user response:

In your example, random_access_iterator<T> and random_access_iterator<const T> are two different and independent classes, jence the compiler does not know how to construct one from another - you need to teach it by providing a constructor (for this case, it is better to have an implicit constructor).

template <typename T>
class random_access_iterator
  /* ... */

 private:
  // Make two iterator classes `friend`s to access private `ptr_`
  template <typename U>
  friend class random_access_iterator;

  /* ... */

 public:
  /* ... */

  // This constructor is only enabled for `const_iterator` to allow "const promotion" of iterators.
  template <bool is_const = std::is_const_v<value_type>,
            typename = std::enable_if_t<is_const>>
  random_access_iterator(
      random_access_iterator<std::remove_const_t<value_type>> iter) : ptr_(iter.ptr) {}

};

CodePudding user response:

I managed to make it work by replacing the CopyConstructor and CopyAssignementOverload with

template<typename U>
random_access_iterator( const random_access_iterator<U>& src ) { *this = src; }
template<typename U>
random_access_iterator& operator= ( const random_access_iterator<U>& src ) { this->_ptr = src._ptr; return *this; }

and by adding a template<typename U> friend class random_access_iterator; private member

  • Related