Попытка написать std :: iterator: ошибка компиляции - PullRequest
1 голос
/ 31 марта 2010

Я пытаюсь написать std::iterator для класса CArray<Type,ArgType> MFC. Вот что я сделал до сих пор:

template <class Type, class ArgType>
class CArrayIterator : public std::iterator<std::random_access_iterator_tag, ArgType>
{
public:
    CArrayIterator(CArray<Type,ArgType>& array_in, int index_in = 0)
        : m_pArray(&array_in), m_index(index_in)
    {
    }

    void operator++() { ++m_index; }
    void operator++(int) { ++m_index; }
    void operator--() { --m_index; }
    void operator--(int) { --m_index; }
    void operator+=(int n) { m_index += n; }
    void operator-=(int n) { m_index -= n; }
    typename ArgType operator*() const{ return m_pArray->GetAt(m_index); }
    typename ArgType operator->() const { return m_pArray->GetAt(m_index); }
    bool operator==(const CArrayIterator& other) const
    {
        return m_pArray == other.m_pArray && m_index == other.m_index;
    }
    bool operator!=(const CArrayIterator& other) const
    {
        return ! (operator==(other));
    }

private:
    CArray<Type,ArgType>* m_pArray;
    int m_index;
};

Я также предоставил две вспомогательные функции для создания итераторов, таких как:

template<class Type, class ArgType>
CArrayIterator<Type,ArgType> make_begin(CArray<Type,ArgType>& array_in)
{
    return CArrayIterator<Type,ArgType>(array_in, 0);
}

template<class Type, class ArgType>
CArrayIterator<Type,ArgType> make_end(CArray<Type,ArgType>& array_in)
{
    return CArrayIterator<Type,ArgType>(array_in, array_in.GetSize());
}

Чтобы проверить код, я написал простой class A и попытался использовать его так:

class A
{
public:
    A(int n): m_i(n)
    {
    }

    int get() const
    {
        return m_i;
    }

private:
    int m_i;
};
struct Test
{
    void operator()(A* p)
    {
        std::cout<<p->get()<<"\n";
    }
};

int main(int argc, char **argv) 
{
    CArray<A*, A*> b;

    b.Add(new A(10));
    b.Add(new A(20));

    std::for_each(make_begin(b), make_end(b), Test());
        return 0;
}

Но когда я компилирую этот код, я получаю следующую ошибку:

Ошибка 4, ошибка C2784: 'bool std :: operator <(const std :: _ Tree <_Traits> &, const std :: _ Tree <_Traits> &) ': не удалось вывести аргумент шаблона для 'const std :: _ Tree <_Traits> & 'from 'CArrayIterator' C: \ Program Файлы \ Microsoft Visual Studio 9.0 \ VC \ include \ xutility 1564 Vs8Console

Кто-нибудь может пролить свет на то, что я делаю неправильно, и как это можно исправить? Я использую компилятор VC9, если это имеет значение.

Ответы [ 2 ]

4 голосов
/ 31 марта 2010

Вы сказали, что ваш итератор является «итератором с произвольным доступом». Часть требований к итераторам произвольного доступа заключается в том, что вы предоставляете операторы сравнения <, <=, > и >=, а < дает строгий слабый порядок и обычные отношения между ними.

Вам необходимо предоставить соответствующие операторы сравнения, или вы можете рассмотреть возможность «понижения рейтинга» до двунаправленного итератора.

3 голосов
/ 31 марта 2010

В зависимости от того, что вы пытаетесь сделать, вам может вообще не понадобиться писать класс итераторов. CArray s похожи на vector s в том, что базовое хранилище данных является просто массивом в стиле C, а класс управляет выделением и освобождением для вас. Вы можете использовать GetData(), чтобы получить указатель на сами данные, и использовать простую математику указателя, чтобы найти конец; почти так же, как вы использовали бы необработанные массивы в стиле C с STL <algorithm> s. Для остроумия:

#define _AFXDLL
#include <afx.h>
#include <afxwin.h>         // MFC core and standard components
#include <afxtempl.h>

#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
    CArray<int, int> ints;
    srand((unsigned)time(0));
    for( int i = 0; i < 10; ++i )
        ints.Add(rand()%10);

    vector<int> ints2;
    copy(ints.GetData(), ints.GetData()+ints.GetCount(), back_inserter(ints2));

    cout << "Original : ";
    copy(ints.GetData(), ints.GetData()+ints.GetCount(), ostream_iterator<int>(cout, " "));
    cout << endl
        << endl
        << "Copy : ";

    copy(ints2.begin(), ints2.end(), ostream_iterator<int>(cout, " "));
    cout << endl;

    return 0;

}

...