views:

118

answers:

2

I am trying to write an std::iterator for the CArray<Type,ArgType> MFC class. This is what I have done till now:

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

I also provided two helper functions to create the iterators like this:

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

To test the code, I wrote a simple class A and tried to use it like this:

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

But when I compile this code, I get the following error:

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

Can anybody throw some light on what I am doing wrong and how it can be corrected? I am using VC9 compiler if it matters.

+4  A: 

You've said that your iterator is a "random access iterator". Part of the requirements for random access iterators is that you provide <, <=, > and >= comparision operators, with < giving a strict weak ordering and the usual relationships between them.

You need to provide the appropriate comparison operators, or you could consider 'downgrading' to a bi-directional iterator.

Charles Bailey
Yes, changed to bidirectional iterator, its working fine now. Thanks. Could not understand what that error was trying to tell.
Naveen
@Naveen: Since your iterator is based on an index, it should be easy to make it a random access iterator. Since the necessary `+=` and `-=` are already in place, just add the comparison operators. These could easily be implemented as comparing `m_index` and you're done.
sbi
@sbi: yes, that makes better sense than changing it to bidirectional iterator. Will implement the functions and change it to random access iterator.
Naveen
+1  A: 

Depending on what you're trying to do, you may not need to write an iterator class at all. CArrays are similar to vectors in that the underlying data store is just a C-style array and the class manages allocation & deallocation for you. You can use GetData() to get a pointer to the data itself, and use simple pointer math to find the end; much the same way you would use raw C-style arrays with the STL <algorithm>s. To wit:

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

}

John Dibling