2016-12-08 8 views
3

std :: find()でユーザー定義の反復子引数を渡すと、GCC 5.2.1。C++ STL関数find()はユーザー定義クラスの反復子引数を受け入れません

(1)

/usr/include/c++/5/bits/stl_algo.h:162:34: error: no matching function for call to ‘__iterator_category(Text_iterator&)’
std::__iterator_category(__first));

(2)

/usr/include/c++/5/bits/stl_iterator_base_types.h:204:5: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits’

エラーがfind_txt内部にある線auto p = find(first, last, first_char);、(によって引き起こされる:(Ubuntuの15.10で)コンパイラは、2つのエラーメッセージを返します) 関数。行がコメントアウトされると、コードはシームレスにコンパイルされます。私は、エラーメッセージに記載されたファイルを参照

#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);や問題の嘘はない。ここでエラーが発生したコードの抜粋ですそれらの2つのGCCライブラリファイル、つまりstl_algo.hとstl_iterator_base_types.hはありますか?それを処理する方法は何か?

私は、運動6、Stroustrupの第20章、第のプログラミング:C++を使用した原理と実践、第2版を作成するためのコードを準備していました。ここにはまった。インターネット上でstd :: find()の問題を検索することは役に立たなかった。この関数の反復子の引数を参照した質問はありません。

+2

TL; DR:あなた 'Text_iterator'は、あなたがそれをそのように名前を付けるという理由だけで、イテレータではありません。標準によってイテレータに課せられた要件を満たしません。 –

+1

も参照してください。http://stackoverflow.com/questions/1724009/why-doesnt-my-custom-iterator-work-with-the-stl-copy –

答えて

8

標準アルゴリズム(std::findを含む)では、使用されたイテレータがIteratorのコンセプトの要件を満たしている必要があります。これらの要件の中で、エラーメッセージによると

std::iterator_traits<It> has member typedefs value_type , difference_type , reference , pointer , and iterator_category

おそらくstd::iterator_traits<Text_iterator>を指し

no type named ‘iterator_category’ in ‘struct std::iterator_traits’

です。したがって、カスタムイテレータは、要件を満たしていないため、イテレータではありません。

解決策:カスタムイテレータタイプのテンプレートを特殊化し、必要なメンバタイプを定義します。また、std::findが必要なので、Iteratorの他の要件とInputIteratorが満たされていることを確認してください。

例特化:

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; 
    }; 
} 
+1

'std :: iterator_traits'を特化する方法の例が役に立ちますそれは直観的に明らかではないので、あまりにも。 –

+0

@MarkRansomが例を追加しました。 – user2079303

+2

もう1つのアプローチ(推奨)は、コードにアクセスできる場合は、イテレータ自体に固有のtypedefを追加することです。 –

関連する問題