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