2010-03-31 3 views
1

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

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

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

Error 4 error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)' : could not deduce template argument for 'const std::_Tree<_Traits> &' from 'CArrayIterator' C:\Program Files\Microsoft Visual Studio 9.0\VC\include\xutility 1564 Vs8Console

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

ответ

4

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

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

+0

Да, изменился двунаправленным итератор, его теперь работает отлично. Благодарю. Не мог понять, что эта ошибка пыталась рассказать. – Naveen

+0

@Naveen: Поскольку ваш итератор основан на индексе, его должно быть легко сделать итератором с произвольным доступом. Поскольку необходимые '+ =' и '- =' уже созданы, просто добавьте операторы сравнения. Они могут быть легко реализованы как сравнение «m_index», и все готово. – sbi

+0

@sbi: да, это имеет смысл, чем изменить его на двунаправленный итератор. Будет реализовывать функции и изменять их на итератор случайного доступа. – Naveen

3

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

#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; 

}

Смежные вопросы