I am coding my very own vector container. To do so, I have a vector class and a RAIterator
(Random Access Iterator) class. In my vector class I am implementing all of std::vector member functions. Amongst them is begin()
which returns an iterator to the first element of the vector. There is also an overload which returns a constant iterator. My functions look like this:
iterator begin() { return (iterator(_data)); }
const_iterator begin() const { return (const_iterator(_data)); }
Here iterator
and const_iterator
are the same as in iterator_traits. My main looks like this:
int main(void)
{
ft::vector<int> v;
ft::vector<int>::iterator it2 = v.begin();
ft::vector<int>::const_iterator it = v.begin();
}
ft
is the namespace I am using to create my vector. The first call to v.begin()
is alright but the second is not. This is because the first begin()
function is called both times and since it returns iterator
, the compiler tells me that there is no available conversion from iterator
to const_iterator
. Here is the actual error I receive:
main.cpp:70:34: error: no viable conversion from 'RAIterator<ft::vector<int, std::__1::allocator<int> >::pointer>' to
'RAIterator<ft::vector<int, std::__1::allocator<int> >::const_pointer>'
ft::vector<int>::const_iterator it = v.begin();
^ ~~~~~~~~~
./iterators/RAIterator.hpp:49:9: note: candidate constructor not viable: no known conversion from 'ft::vector<int,
std::__1::allocator<int> >::iterator' (aka 'RAIterator<int *>') to 'const int *' for 1st argument
RAIterator(T src) : _ptr(src) { /*std::cout << "Second constructor called" << std::endl;*/ }
^
./iterators/RAIterator.hpp:50:9: note: candidate constructor not viable: no known conversion from 'ft::vector<int,
std::__1::allocator<int> >::iterator' (aka 'RAIterator<int *>') to 'const ft::RAIterator<const int *> &' for 1st argument
RAIterator(const RAIterator &src) : _ptr(src._ptr) { /*std::cout << "Third constructor called" << std::endl;*/ } // CHANGE
^
1 error generated.
Here are my RAIterator
class constructors:
RAIterator() : _ptr(NULL) { /*std::cout << "First constructor called" << std::endl;*/ }
RAIterator(T src) : _ptr(src) { /*std::cout << "Second constructor called" << std::endl;*/ }
RAIterator(const RAIterator &src) : _ptr(src._ptr) { /*std::cout << "Third constructor called" << std::endl;*/ } // CHANGE
I don't know how to solve this problem, ie how to make this conversion possible. If I write std
instead of ft
it compiles correctly, so I have to be able to support this conversion.
PS I have to use C++98. Weird, right?
You can add a converting constructor.
In C++98 there aren't all the helpful traits to only allow the template constructor when T
is pointer to const, and U
is the corresponding pointer to mutable, so it will always participate in overload resolution, but instantiating it will fail for incompatible pointer types.
template<typename T>
class RAIterator {
T _ptr;
public:
RAIterator() : _ptr(nullptr) {}
RAIterator(T src) : _ptr(src) {}
RAIterator(const RAIterator &src) : _ptr(src._ptr) {}
template<typename U>
// requires std::same_as<std::remove_pointer_t<T>, const std::remove_pointer_t<U>>
RAIterator(const RAIterator<U> &src) : _ptr(src._ptr) {}
// all your existing stuff
};
C++ does not support function overloading based on return types, only on argument types (where this
is also considered an argument). So there is no way for the compiler to distinguish the two v.begin()
calls.
If you call begin()
on a const
object, you'll see that it calls the const
overload:
ft::vector<int> const &const_v = v;
ft::vector<int>::const_iterator it = const_v.begin();
But that is a bit silly, of course.
In C++11, cbegin
and cend
were added to make this easier.
But why does it work unmodified in std::vector
? I can't find any documentation on this, but I think the reason must be that std::vector::iterator
supports implicit conversion to std::vector::const_iterator
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.