简体   繁体   English

将 vector<>::const_iterator 转换为 vector<>::iterator

[英]Converting vector<>::const_iterator to vector<>::iterator

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.为此,我有一个向量 class 和一个RAIterator (随机访问迭代器)class。在我的向量 class 中,我正在实现所有 std::vector 成员函数。 Amongst them is begin() which returns an iterator to the first element of the vector.其中有begin() ,它返回指向向量第一个元素的迭代器。 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.这里iteratorconst_iterator和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. ft是我用来创建矢量的名称空间。 The first call to v.begin() is alright but the second is not.第一次调用v.begin()没问题,但第二次不行。 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 .这是因为第一个begin() function 被调用了两次,并且由于它返回iterator ,编译器告诉我没有从iteratorconst_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 class 构造函数:

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.如果我写std而不是ft它编译正确,所以我必须能够支持这种转换。

PS I have to use C++98. PS我必须使用 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.在 C++98 中,当T是指向 const 的指针,并且U是对应的指向可变指针时,并没有只允许模板构造函数的所有有用特性,因此它将始终参与重载决议,但实例化它会失败不兼容的指针类型。

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). C++ 不支持基于返回类型的 function 重载,仅支持参数类型( this也被视为参数)。 So there is no way for the compiler to distinguish the two v.begin() calls.所以编译器无法区分这两个v.begin()调用。

If you call begin() on a const object, you'll see that it calls the const overload:如果你在const object 上调用begin() ,你会看到它调用了const重载:

    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.在 C++11 中, 添加cbegincend以使这更容易。

But why does it work unmodified in std::vector ?但为什么它在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 .我找不到关于此的任何文档,但我认为原因一定是std::vector::iterator支持隐式转换为std::vector::const_iterator

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM