2

ここでトピックに対する多くの回答を見つけましたが、コードを実行できませんでした。

編集: 投稿された例は、不足しているものを導入した後に機能するようになりました。この例を自分の実験の基礎として使用できることを願っています。また、この例をランダム アクセス イテレータとして使用するために不足しているものも紹介しました。binary_search アルゴリズムを使用すると、はるかに効率的に機能します。

独自のイテレータを作成する必要がある場合、value_type やその他の「スペシャル」を操作するのに苦労します。

ここでイテレータを書かない方法について多くの記事を読みましたが、実際の例を得ることができませんでした。特に、イテレータから派生してはならないことを読みました。だから私は愚かにもう一度尋ねます:

イテレータの value_type を定義するにはどうすればよいですか。クラス定義では機能せず、type_traits 構造体を手動で定義しても機能しませんでした。続行方法がわかりません...

     #include <iostream>
     #include <algorithm>
     #include <type_traits>
     #include <iterator>

    using namespace std;

    int data[]= { 1,4,7,9,11,20,28 }; //Sorted data

    template < typename T >
    class MyIter
    {
        int offset;
        T* base;

        public:
        typedef int value_type;

        //add the following lines after reading the answers -> it works! 
        typedef std::ptrdiff_t difference_type;
        typedef T * pointer;
        typedef T & reference;
        typedef std::forward_iterator_tag iterator_category;

        // if you want to use as random access iterator:
        // typedef std::random_access_iterator_tag iterator_category;

        public:
        MyIter( T* _base, int _offset) : base(_base), offset(_offset) {}
        MyIter() {}

        bool operator !=( const MyIter& rhs) 
        {
            T* tmp1= base+offset;
            T* tmp2= rhs.base + rhs.offset;

            return tmp1 != tmp2;
        } 

        MyIter operator++(int)
        {
            MyIter tmp(*this);
            offset++;
            return tmp;
        }

        T operator*()
        {
            return *(base+offset);
        }

        // Addition: if used as random access iterator you must provide:
        int operator-(const MyIter& rhs)
        {
            return offset-rhs.offset;
        }

        MyIter operator+=(int off)
        {
            offset+=off;
            return *this;
        }


    };

    typedef MyIter<int> iterType ;

    int main()
    {
        cout << "ok" << endl;

        pair<iterType, iterType> bounds;

        MyIter<int> start( data,0);
        MyIter<int> ende ( data,7);

        bounds = equal_range( start, ende, 28 );

        for ( iterType it= bounds.first; it!=bounds.second; it++)
        {
            cout << "Found " << *it << endl;
        }


        return 0;
    }
4

3 に答える 3

3

value_type標準ライブラリがイテレータから必要とするものに加えて、いくつかの定義がありません。

typedef std::ptrdiff_t difference_type;
typedef T * pointer;
typedef T & reference;
typedef std::forward_iterator_tag iterator_category;    

または、から継承するstd::iterator<std::forward_iterator_tag, T>と、これらが得られます。あなたがそれをすべきではないことをどこで読んだのかわかりませんが、それはまさにそのためのものstd::iteratorです.

さらに、プレインクリメント演算子がありません。

MyIter operator++()
{
    ++offset;
    return *this;
}

また->==演算子。また、逆参照演算子は、値または参照を返すオーバーロードを使用*it = 42して、おそらく allow への参照を返す必要があります。constconst

于 2013-02-06T12:54:05.207 に答える
1

いくつかの重要な型メンバーとプレインクリメント演算子がありません(@MikeSeymourが指摘した他の逆参照および比較演算子も多数あります)。thise をクラス定義に追加してください (現在欠落しているプリインクリメント演算子に関して、ポストインクリメント演算子を書き直したことに注意してください) binary_search

typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;

MyIter& operator++()
{
    ++offset;
    return *this;                      
}

MyIter operator++(int)
{
    MyIter tmp(*this);
    ++*this; // NOTE this will call the other operator++
    return tmp;
}

LiveWorkSpaceでの出力@JamesKanzeが指摘したように、これらの不足している typedef は、から継承することによって提供されstd::iterator<std::forward_iterator_tag, T>ます。

于 2013-02-06T12:49:48.617 に答える
1

std::binary_searchランダム アクセス イテレータが必要です。つまり、反復子は、ポインターとまったく同じセマンティクスで加算と減算 ( ++=-および) をサポートする必要があります。-=また、任意の数のアルゴリズムでも、イテレーターに多数の typedef が必要です。派生 std::iterator元は、それらを取得する最も簡単な方法です。(技術的には、標準が必要とするのはstd::iterator_traits、正しい値を生成することです。そのため、イテレータに対して明示的にインスタンス化できます。ただし、デフォルトの実装では、イテレータ クラスで typedef が選択されます。)

編集:

あなたの投稿を読み直してください:あなた間違いなくから公に派生する必要がありますstd::iterator。そうでないと言う人は誰でも間違っています。

于 2013-02-06T12:45:13.883 に答える