【问题标题】:The C++ STL function find() doesn't accept the iterator arguments of a user-defined classC++ STL 函数 find() 不接受用户定义类的迭代器参数
【发布时间】:2017-04-23 23:20:49
【问题描述】:

当我在 std::find() 中传递用户定义的迭代器参数时,GCC 5.2.1.编译器(在 Ubuntu 15.10 上)给出了两条错误消息:

(1)

/usr/include/c++/5/bits/stl_algo.h:162:34:错误:没有匹配 调用“__iterator_category(Text_iterator&)”的函数
std::__iterator_category(__first));

(2)

/usr/include/c++/5/bits/stl_iterator_base_types.h:204:5:错误:否 “struct std::iterator_traits”中名为“iterator_category”的类型

错误是由 find_txt() 函数内部的auto p = find(first, last, first_char); 行引起的。当该行被注释掉时,代码会无缝编译。以下是导致错误的代码摘录:

#include "std_lib_facilities.h"//from B. Stroustrup's site

using Line = vector<char>;

class Text_iterator {

    list<Line>::iterator ln; //points to lines
    Line::iterator pos; //points to characters

    public: 
    Text_iterator(list<Line>::iterator ll, Line::iterator pp)
        :ln{ll}, pos{pp} { }
    char& operator*() { return *pos; }
    Text_iterator& operator++();
    bool operator==(const Text_iterator& other) const
        { return ln==other.ln && pos==other.pos; }
    bool operator!=(const Text_iterator& other) const
        { return !(*this==other); }
};

Text_iterator& Text_iterator::operator++()
{
    ++pos;
    if (pos==(*ln).end()) {
    ++ln;
    pos = (*ln).begin();
}
    return *this;
}

Text_iterator find_txt(Text_iterator first, Text_iterator last, const string& s)
{
    if (s.size()==0) return last;// can’t find an empty stringchar first_char = s[0];
    char first_char = s[0];
    while (true) {
        auto p = find(first, last, first_char); //<------------the PROBLEM!!!!!!
        //if (p==last || match(p,last,s)) return p;
        //first = ++p;// look at the next character
    }
}

void ex6()
{
    ;
}


int main()
{
    ex6();
}

我参考了错误消息中提到的文件:

template<typename _Iterator, typename _Predicate>
    inline _Iterator
    __find_if(_Iterator __first, _Iterator __last, _Predicate __pred)
    {
        return __find_if(__first, __last, __pred,
        std::__iterator_category(__first)); //this is line #162 in stl_algo.h
    }

template<typename _Iter>
    inline typename iterator_traits<_Iter>::iterator_category
    __iterator_category(const _Iter&)//this is line #204 in stl_iterator_base_types.h
    { return typename iterator_traits<_Iter>::iterator_category(); }

问题出在auto p = find(first, last, first_char); 还是这两个GCC 库文件——即stl_algo.h 和stl_iterator_base_types.h?有哪些可能的处理方法?

我正在为 Stroustrup 的Programming: Principles and Practice Using C++第 2 版第 20 章的练习 6 准备代码。并被困在这里。在 Internet 上搜索 std::find() 问题无济于事。没有一个问题涉及此函数的迭代器参数。

【问题讨论】:

标签: c++ templates stl iterator


【解决方案1】:

标准算法(包括std::find)要求使用的迭代器满足Iterator概念的要求。其中的要求是

std::iterator_traits&lt;It&gt; 的成员类型定义为 value_typedifference_typereferencepointeriterator_category

根据报错信息,

“struct std::iterator_traits”中没有名为“iterator_category”的类型

这可能是指std::iterator_traits&lt;Text_iterator&gt;。因此,显然自定义迭代器不是迭代器,因为它不符合要求。

解决方案:为自定义迭代器类型专门化std::iterator_traits 模板并定义所需的成员类型。还要确保满足 Iterator 的其他要求以及 InputIterator,因为这是 std::find 的要求。

专业化示例:

namespace std {
    template<>
    struct iterator_traits<Text_iterator> {
        typedef ptrdiff_t          difference_type;
        typedef char               value_type;
        typedef char*              pointer;
        typedef char&              reference;
        typedef input_iterator_tag iterator_category;
    };
}

【讨论】:

  • 一个如何专门化std::iterator_traits 的例子也会很有用,因为它并不直观。
  • @MarkRansom 添加了一个示例。
  • 另一种方法(首选)是向迭代器本身添加必要的 typedef,如果您可以访问其代码。
  • 当我在 Text_iterator 中添加 typedef 时,我得到了这个答案:
  • @Jarisleif 如果你仔细查看你的类定义,你会发现你没有定义Text_iterator::operator++()。链接器告诉你这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-13
  • 2014-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多