1

これは簡単な演習です。C スタイルの文字配列用のカスタム イテレータをすべて自分で書きたいと思います。ブーストはありません。中途半端だと思うのですが、使用するとエラーが出てしまいますstd::count

私のイテレータはこれです:

class myIterator : std::iterator<std::input_iterator_tag, char>
{
    char *p;

public:

    // Definitions
    typedef typename std::iterator<std::input_iterator_tag, char>::difference_type difference_type;
    typedef typename std::iterator<std::input_iterator_tag, char>::value_type value_type;
    typedef typename std::iterator<std::input_iterator_tag, char>::reference reference;
    typedef typename std::iterator<std::input_iterator_tag, char>::pointer pointer;

    // Implementation
    myIterator(char* x) :p(x) { };
    myIterator(const myIterator& i) : p(i.p) { };
    myIterator& operator++() { ++p; return *this; };
    myIterator operator++(int) {myIterator tmp(*this); operator++(); return tmp; };
    bool operator==(const myIterator& rhs) { return p == rhs.p; };
    bool operator!=(const myIterator& rhs) { return p != rhs.p; };
    char& operator*() { return *p; };
};

したがって、forループでイテレータを使用すると、それは素晴らしいことです。

for (auto it = data.begin(); it != data.end(); it++)
   std::cout << *it;

ただし、これはコンパイル時エラーになります。

std::cout << std::count(data.begin(), data.end(), '@') << std::endl;

価値があるのは、 anddataの古典的なラッピング関数(つまり、and ) を備えた非常に単純なクラスです。begin()end()return myIterator(address_);return myIterator(address_ + size_);

私には不可解なエラーは何ですか:

error: no matching function for call to 'count'
[...]
note: candidate template ignored: substitution failure [with _InputIterator = myIterator, _Tp = char]: no type named 'difference_type' in 'std::__1::iterator_traits<myIterator>'
count(_InputIterator __first, _InputIterator __last, const _Tp& __value_)

difference_typeここに何かが欠けています:イテレータで宣言しました。

誰でも助けることができますか?

4

2 に答える 2

5

、などからクラスを派生させると、std::iteratorすでに定義されているvalue_typeためdifference_type、それらを定義するべきではありません。継承を公開してそれらを削除するだけで機能しますtypedef

class myIterator : public std::iterator<std::input_iterator_tag, char>
{
    char *p;

public:
    // Implementation
    myIterator(char* x) :p(x) { };
    // ......
};

sを削除する必要typedefはありませんが、手動で定義する理由はないことに注意してくださいstd::iterator。既に削除されています。

ここでデモ。

于 2013-10-16T13:27:50.133 に答える
2

これが問題かどうかはわかりませんが、通常の使用方法は std::iteratorpublic から継承することです。または、それを使用せず、その typedef の5 つすべてを定義します。コードが機能しない理由は、 の typedef にiterator_category アクセスできないためだと思います。 から公に派生していない場合は std::iterator、それを提供する必要があります。

価値のあることとして、イテレータの型を適合させる 3 つの方法があります: からパブリックに継承std::iteratorする、5 つの typedef ( value_typedifference_typepointerreferenceおよびiterator_category) をクラスで直接 (パブリックとして) 宣言するか、またはクラスを特殊化std::iterator_traitsします (再び、5 つのtypedef)。1 つ目は、最も単純で最も一般的なものです。

于 2013-10-16T13:29:32.927 に答える