从begin()获取const_iterator而不是cbegin()

3
如果我取消注释foo::const_iterator j = f.begin();这一行,为什么下面的代码无法编译呢?但是,如果我使用foo::const_iterator j = f.cbegin();这行代码,就可以成功编译。我试图让这行代码和我的std::vector例子一样正常工作。
#include <vector>

struct foo {
    struct node { };
    node *first = nullptr, *last = nullptr;

    struct base_iterator {
        node* ptr;
        base_iterator (node* n) : ptr(n) { }
    };

    struct iterator : base_iterator { using base_iterator::base_iterator; };

    struct const_iterator : base_iterator { using base_iterator::base_iterator; };

    iterator begin() { return iterator(first); }
    const_iterator begin() const { return const_iterator(first); }
    const_iterator cbegin() const { return const_iterator(first); }
};

// Test

int main() {
    foo f;
    foo::iterator i = f.begin();
//  foo::const_iterator j = f.begin();  // Won't compile because f is not const.
//  foo::const_iterator j = f.cbegin();  // Will compile fine.

    std::vector<int> v;
    std::vector<int>::const_iterator it = v.begin();  // Compiles even though v is not const.
}

3
为什么你期望它可以工作?不同的类型,全部都要考虑进去。对于“vector”,这并非魔法般地发生。迭代器被设计为具备可用的转换。 - StoryTeller - Unslander Monica
我需要在我的迭代器和const_iterator类中做哪些更改才能使其像std::vector<int>::const_iterator一样工作? - prestokeys
添加一个转换构造函数,或者一个转换操作符。 - StoryTeller - Unslander Monica
那么在const_iterator类中定义运算符const_iterator& operator=(const iterator& other),或者类似的复制构造函数? - prestokeys
不是赋值运算符,而是转换运算符。请稍等。 - StoryTeller - Unslander Monica
@prestokeys 这不是一个复制构造函数。它只是一个 普通 构造函数,接受 某个其他类型 的参数。 - Caleth
1个回答

4
它适用于std::vector,因为所有标准库容器的迭代器都被设计成支持iterator-->const_iterator转换。这旨在模仿指针转换的工作原理。
每当您的两个迭代器是用户定义的类时,您需要明确添加它。您有两个选项:
一个转换构造函数:
struct iterator : base_iterator { using base_iterator::base_iterator; };

struct const_iterator : base_iterator {
   using base_iterator::base_iterator;
   const_iterator(const iterator& other) : base_iterator(other) {}
};

一个转换运算符:
struct const_iterator : base_iterator { using base_iterator::base_iterator; };

struct iterator : base_iterator {
  using base_iterator::base_iterator; 
  operator const_iterator() const { /* ... */ }
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接