【问题标题】:Custom STL iterator implementation error自定义 STL 迭代器实现错误
【发布时间】:2014-05-23 14:23:33
【问题描述】:

为了概念验证,我正在尝试编写一个类似 STL 的迭代器,它将通过跳过所有其他字符来迭代字符串。但是,我遇到了许多我无法理解的奇怪 C++ 错误。

我的代码是:

#include<iostream>
#include<string>

using std::string;

class TestIterator : public std::iterator<std::forward_iterator_tag, string> {
private:
  string::iterator _it;

public:
  TestIterator() {}

  string& operator++() {
    return _it + 2;
  }

  string& operator=(const string& other) {
    _it = other;
  }
};

int main(int argc, char** argv) {
  string a("123045678");
  TestIterator start = a.begin();
  TestIterator end = a.end();
  string b(start, end);

  std::cout << b << std::endl;

  return 0;
}

当我编译它时,我得到:

% g++ -std=gnu++0x test.cpp -o test
test.cpp: In member function ‘std::string& TestIterator::operator++()’:
test.cpp:14:16: error: invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string<char>&}’ from an rvalue of type ‘__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >’
     return _it + 2;
                ^
test.cpp: In member function ‘std::string& TestIterator::operator=(const string&)’:
test.cpp:18:9: error: no match for ‘operator=’ (operand types are ‘std::basic_string<char>::iterator {aka __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >}’ and ‘const string {aka const std::basic_string<char>}’)
     _it = other;
         ^
test.cpp:18:9: note: candidates are:
In file included from /usr/include/c++/4.8/bits/stl_algobase.h:67:0,
                 from /usr/include/c++/4.8/bits/char_traits.h:39,
                 from /usr/include/c++/4.8/ios:40,
                 from /usr/include/c++/4.8/ostream:38,
                 from /usr/include/c++/4.8/iostream:39,
                 from test.cpp:1:
/usr/include/c++/4.8/bits/stl_iterator.h:708:11: note: __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >& __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >::operator=(const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&)
     class __normal_iterator
           ^
/usr/include/c++/4.8/bits/stl_iterator.h:708:11: note:   no known conversion for argument 1 from ‘const string {aka const std::basic_string<char>}’ to ‘const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&’
/usr/include/c++/4.8/bits/stl_iterator.h:708:11: note: __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >& __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >::operator=(__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&&)
/usr/include/c++/4.8/bits/stl_iterator.h:708:11: note:   no known conversion for argument 1 from ‘const string {aka const std::basic_string<char>}’ to ‘__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&&’
test.cpp: In function ‘int main(int, char**)’:
test.cpp:24:32: error: conversion from ‘std::basic_string<char>::iterator {aka __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >}’ to non-scalar type ‘TestIterator’ requested
   TestIterator start = a.begin();
                                ^
test.cpp:25:28: error: conversion from ‘std::basic_string<char>::iterator {aka __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >}’ to non-scalar type ‘TestIterator’ requested
   TestIterator end = a.end();
                            ^
In file included from /usr/include/c++/4.8/string:53:0,
                 from /usr/include/c++/4.8/bits/locale_classes.h:40,
                 from /usr/include/c++/4.8/bits/ios_base.h:41,
                 from /usr/include/c++/4.8/ios:42,
                 from /usr/include/c++/4.8/ostream:38,
                 from /usr/include/c++/4.8/iostream:39,
                 from test.cpp:1:
/usr/include/c++/4.8/bits/basic_string.tcc: In instantiation of ‘static _CharT* std::basic_string<_CharT, _Traits, _Alloc>::_S_construct(_InIterator, _InIterator, const _Alloc&, std::forward_iterator_tag) [with _FwdIterator = TestIterator; _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’:
/usr/include/c++/4.8/bits/basic_string.h:1725:56:   required from ‘static _CharT* std::basic_string<_CharT, _Traits, _Alloc>::_S_construct_aux(_InIterator, _InIterator, const _Alloc&, std::__false_type) [with _InIterator = TestIterator; _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
/usr/include/c++/4.8/bits/basic_string.h:1746:58:   required from ‘static _CharT* std::basic_string<_CharT, _Traits, _Alloc>::_S_construct(_InIterator, _InIterator, const _Alloc&) [with _InIterator = TestIterator; _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
/usr/include/c++/4.8/bits/basic_string.tcc:229:49:   required from ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(_InputIterator, _InputIterator, const _Alloc&) [with _InputIterator = TestIterator; _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
test.cpp:26:22:   required from here
/usr/include/c++/4.8/bits/basic_string.tcc:128:12: error: no match for ‘operator==’ (operand types are ‘TestIterator’ and ‘TestIterator’)
  if (__beg == __end && __a == _Alloc())
            ^
/usr/include/c++/4.8/bits/basic_string.tcc:128:12: note: candidates are:
...

有没有其他方法可以做这样的事情(即,在字符串类上提供一个新的迭代器)而不将迭代器存储在我的类中作为迭代器?我已经从网上许多不同的代码清单中拼凑出这个类,所以语义可能并不完美。

我们将不胜感激任何有关解决此迭代器问题的帮助。

【问题讨论】:

  • _sBegin 等是std::string::iterators,但您的方法返回string&amp;。这是行不通的,这是编译器告诉你的。
  • 澄清@juanchopanza 的观点——字符串迭代器返回对字符串元素的引用(例如char)。您正在返回对整个字符串的引用。
  • 你考虑过使用boost::iterator_facade吗?它解决了实现自己的迭代器的大部分烦恼。
  • @BillyONEal 我还没有研究过提升。如果可以避免的话,我宁愿不引入进一步的依赖。
  • Boost 在技术上可能是一个依赖项,但重新滚动已经在 Boost 中的东西是一种责任。

标签: c++ c++11 stl iterator


【解决方案1】:

STL 迭代器是由容器对象创建的,而不是由容器本身构造的:

int main(int argc, char** argv) {
  string a("abcdefghijk");
  TestIterator start = a.begin();  //<-----------
  TestIterator stop = a.end();  //<-----------
  string b(start, stop); //<-----------

  std::cout << b << std::endl; 

  return 0;
}

因此,您的新迭代器必须能够从string::begin() 返回的string::iterator 构造。

STL 迭代器本身没有begin() 和end();这就是容器的工作。

operator++() 应该返回对正在递增的迭代器的引用,而不是对其指向的容器的引用。

【讨论】:

  • 谢谢,我开始对代码中应该发生的事情有了更多的了解。但是,我仍然看到一些新变化带来的神秘新错误。你能看看我的编辑,看看我哪里出错了吗?
  • 堆栈溢出对这类事情可能有好处,但请务必先阅读更多有关 STL 迭代器的信息。从大量教程中学习 API 的速度会快得多,然后再一头扎进自己的实现中。
猜你喜欢
  • 2011-01-22
  • 1970-01-01
  • 1970-01-01
  • 2018-08-25
  • 2015-05-26
  • 2013-09-23
  • 1970-01-01
  • 2010-10-10
  • 1970-01-01
相关资源
最近更新 更多