拥有不使用std :: binary_search的迭代器类

时间:2013-02-06 12:36:41

标签: c++ iterator

我在这里找到了很多答案,但我无法让我的代码运行。

修改 在发布缺失的东西后,发布的示例现在可用。希望有人可以使用这个例子作为自己实验的基础。我还介绍了使用此示例作为随机访问迭代器的缺失事项。使用binary_search algos可以更有效地工作。

如果我必须编写自己的迭代器,我会使用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;
    }

3 个答案:

答案 0 :(得分: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的引用,const重载返回值或const引用。

答案 1 :(得分:1)

std::binary_search需要随机访问迭代器。哪一个 意味着迭代器必须支持加法和减法 (++=--=),语义完全相同 一个指针。任何数量的算法也会期望 迭代器中的一些typedef:派生自 std::iterator是获取它们的最简单方法。 (从技术上讲, 标准要求的是std::iterator_traits屈服 正确的值,因此您可以显式实例化它 你的迭代器。但它的默认实现选择了typedef 在迭代器类中。)

编辑:

重读你的帖子:你明确地 应该公开地从std::iterator派生。否则谁说错了。

答案 2 :(得分:1)

您缺少几个基本类型成员和预增量运算符(以及@MikeSeymour指出的一堆其他解引用和比较运算符)。将此添加到您的类定义中(请注意,我根据当前缺少的预增量运算符重写了后增量运算符)以使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>提供的。