0

(注意:我写这个项目只是为了学习;关于它是多余的评论是......呃,多余的。;)

我正在尝试实现一个随机访问迭代器,但我发现关于这个主题的文献很少,所以我将通过反复试验结合维基百科的运算符重载原型列表。到目前为止它工作得很好,但我遇到了一个障碍。

代码如

exscape::string::iterator i = string_instance.begin();
std::cout << *i << std::endl;

工作,并打印字符串的第一个字符。但是,*(i + 1) 不起作用,*(1 + i) 也不起作用。我的完整实现显然有点太多了,但这是它的要点:

namespace exscape {
    class string {
        friend class iterator;
    ...
    public:
        class iterator : public std::iterator<std::random_access_iterator_tag, char> {
            ...
            char &operator*(void) {
                return *p; // After some bounds checking
            }
            char *operator->(void) {
                return p;
            }

            char &operator[](const int offset) {
                return *(p + offset); // After some bounds checking
            }

            iterator &operator+=(const int offset) {
                p += offset;
                return *this;
            }

            const iterator operator+(const int offset) {
                iterator out (*this);
                out += offset;
                return out;
            }

        };
};
}

int main() {
    exscape::string s = "ABCDEF";
    exscape::string::iterator i = s.begin();
    std::cout << *(i + 2) << std::endl;
}

以上失败(第 632 行当然是 *(i + 2) 行):

string.cpp:在函数'int main()'中:string.cpp:632:错误:'*exscape::string::iterator::operator+(int)(2)'字符串中的'operator*'不匹配。 cpp:105: 注意:候选人是:char& exscape::string::iterator::operator*()

*(2 + i) 失败:

string.cpp:在函数'int main()'中:string.cpp:632:错误:'2 + i'中的'operator +'不匹配string.cpp:434:注意:候选者是:exscape :: string exscape: :operator+(const char*, const exscape::string&)

我的猜测是我需要做更多的重载,但我不确定我缺少哪个运算符。

4

4 回答 4

9

您的+运算符返回一个 const 迭代器,但您没有 const operator*。加一个,我想你会没事的。或者,正如下面 xtofl 所建议的,您可以将operator*const. 这是更好的设计,除非您operator*出于某种原因确实需要非常量。

于 2009-11-10T17:00:18.063 回答
4

要让它与左边的数字常量一起工作,你需要一个非成员函数。像这样的东西(未经测试的代码):

exscape::string::iterator operator+(exscape::string::iterator it, size_t n) {
    return it += n;
}

exscape::string::iterator operator+(size_t n, exscape::string::iterator it) {
    return it += n;
}
于 2009-11-10T17:05:07.900 回答
3

首先,您需要一个operator *(void) const.

[编辑:根据您现有的运营商,以下应该做:

char &operator *(void) const {
    // bounds checking
    return *p;
}

]

其次,您需要一个operator+(int, exscape::string::iterator). 一个相当常见的写法是(在迭代器类中):

friend const iterator operator+(const int offset, iterator out) {
    out += offset;
    return out;
}

请注意,将其标记为朋友使其成为非成员函数,即使它是在类中定义的。您可能还想将 替换operator+(int)为非成员函数 ,operator+(iterator,int)以便获得应用于 + 的 LHS 和 RHS 的相同隐式转换规则。

const iterator[另一个编辑:正如您在评论中指出的那样, operator+无论如何都不应该返回- 只是 return iterator。因此,对于您的代码示例,您实际上并不需要operator*()const. 但无论如何你应该有一个,因为用户可能想使用你的类的 const 修改实例来编写代码。]

最后,具有随机访问迭代器(包括 std::string)的标准容器将签名定义difference_type为类的成员。int可能不足以包含所有可能的偏移量(例如在 LP64 架构上),但ptrdiff_t它是一个很好的候选者。

于 2009-11-10T17:07:02.357 回答
0

我不相信 *(2 + i) 会起作用,因为左手操作数需要是您自己的类型。您实际上是在告诉编译器将您的迭代器添加到 2,这是没有意义的。(i + 2) 意味着将我的迭代器向前移动两个索引。

有关详细信息,请参阅C++ Faq Lite

于 2009-11-10T17:06:09.993 回答