PDA

View Full Version : C++ woes: defining iterator in own class




sammich
Apr 7, 2009, 11:38 PM
Gudday everyone,

In class we need to recreate part of an STL library (namely the 'set' class) and apply it only for integers. I was trying to define constructors for the iterator and a couple of operators but every instance of 'iterator' throws the error below:

ISO C++ forbids declaration of 'iterator' with no typeI'm sure it's an elementary mistake, but it's going to be one that I'll never make again.

Thanks for any advice in advance,
Sammich.

//IntSet.h

#include <vector>
using std::vector;

class IntSet {
std::vector<int> set;

public:
// constructors
IntSet(void);
IntSet(const IntSet&);
IntSet(vector<int>::const_iterator, vector<int>::const_iterator);

//access methods
int size() const;
void add(int v);
bool remove(int v);
bool contains(int v);
bool empty(void) const;

//begin iterator

typedef vector<int>::iterator iterator;
typedef vector<int>::const_iterator const_iterator;

iterator(void);
iterator(const &iterator);

iterator begin() { return set.begin(); }
const_iterator begin() const { return set.begin(); }
iterator end() { return set.end(); }
const_iterator end() const { return set.end(); }

bool operator==(const &iterator);
bool operator!=(const &iterator);
//end iterator

IntSet operator*();
bool operator!=(IntSet&);
bool operator==(IntSet&);

IntSet operator+(const IntSet&);
IntSet operator*(const IntSet&);
IntSet operator-(const IntSet&);
};



lozanoj83
Apr 8, 2009, 01:00 AM
I asked my roomy, and this is what he said:

The error message: "ISO C++ forbids declaration of 'iterator' with no type"
is saying that it wont let you compile because you dont have a "type" (string, void, int, etc.) before the decleration of "iterator". I just started doing this stuff in C++ so sorry if I'm not help!


I think the error comes up in this piece of code:

iterator(void);
iterator(const &iterator);

maybe you need to have:

void iterator ( //paramter// )
//name type// iterator (const & iterator);

If its not in this piece of code, I'm certain that it is located somewhere where you have have "iterator" declared. Hopefully this helps!

sammich
Apr 8, 2009, 02:55 AM
Thanks to your friend (and you for showing him :)) but I'm trying to make a constructor, and they don't take a return type. Me thinks something else is afoot, do I need to create an iterator class?

I'll throw in all my code in a zip, if some could take a look at it will be much appreciated.

lazydog
Apr 8, 2009, 03:45 AM
Hi

I've had a very quick look at your project and I can see a couple of problems.


class IntSet
{
...
...
...
typedef vector<int>::iterator iterator;
typedef vector<int>::const_iterator const_iterator;

iterator(const iterator&); //copy constructor
...
bool operator==(const & iterator );
bool operator!=(const & iterator );

}


You have a typo in the operator definitions - you've got the & in the wrong place. It should be:-


bool operator==(const iterator & );
bool operator!=(const iterator & );


Also, I'm not sure what you're trying to do in this line:-

iterator(const iterator&); //copy constructor

You can't define a constructor for iterator within IntSet. Anyway, that line is confusing the compiler because your are defining a method name with the same name as your iterator typedef. If you comment this line out and fix the above two typos your program will compile and link... with a few warnings though.

b e n

gnasher729
Apr 8, 2009, 03:57 AM
You can only define a constructor for class iterator inside the declaration of class iterator, not inside class IntSet. It never occurs to the compiler that "iterator (xxx) is supposed to be a constructor, it looks like, well, just a type name followed by an opening parenthesis, so it doesn't make any sense at all.

sammich
Apr 8, 2009, 04:21 AM
Thanks again to people who are helping me out on this. This is part of an assignment due tomorrow (lol) and I can pull it off, I've got testing code, and the pseudocode/logic is written, just this darstardly concept I'm not grasping

Thanks lazydog. I think I'm just having conflicting ideas on how things are meant to be implemented. I was thinking that since the code in the below loop is called from inside IntSet that the iterator definitions sat inside with all the other IntSet definitions.

So should I make a iterator a new class on it's own?

Warning: code tag spam :D

The code below, in main, needs to work on my code:
for (IntSet::iterator i = s.begin(); i != s.end(); i++) {
std::cout << *i << std::endl;
}

How can I get the loop above to still work when iterator is a class sitting outside IntSet?

Modified code: If you'll noticed I left the typedef's in the IntSet class. Scroll down for the iterator class.
//IntSet.h

#include <vector>
using std::vector;

class IntSet {
std::vector<int> set;

public:
// constructors
IntSet(void);
IntSet(const IntSet&);
IntSet(vector<int>::const_iterator, vector<int>::const_iterator);

//accessor/validator methods
int size() const; // #
void add(int v); // #
bool remove(int v); // #
bool contains(int v); // #
bool empty(void) const; // #

typedef vector<int>::iterator iterator;
typedef vector<int>::const_iterator const_iterator;

IntSet operator*();
bool operator!=(IntSet&);
bool operator==(IntSet&);

IntSet operator+(const IntSet&);
IntSet operator*(const IntSet&);
IntSet operator-(const IntSet&);
};


class iterator {

public:
iterator();
iterator(const iterator&); //copy constructor

iterator begin() { return IntSet.set.begin(); }
const_iterator begin() const { return IntSet.set.begin(); }
iterator end() { return IntSet.set.end(); }
const_iterator end() const { return IntSet.set.end(); }

bool operator==(const iterator&);
bool operator!=(const iterator&);
};

Errors:
/Users/samuelchan/Desktop/IntSet/IntSet.h:56: error: ‘const_iterator’ does not name a type
/Users/samuelchan/Desktop/IntSet/IntSet.h:58: error: ‘const_iterator’ does not name a type
/Users/samuelchan/Desktop/IntSet/IntSet.h: In member function ‘iterator iterator::begin()’:
/Users/samuelchan/Desktop/IntSet/IntSet.h:55: error: expected primary-expression before ‘.’ token
/Users/samuelchan/Desktop/IntSet/IntSet.h: In member function ‘iterator iterator::end()’:
/Users/samuelchan/Desktop/IntSet/IntSet.h:57: error: expected primary-expression before ‘.’ token

lazydog
Apr 8, 2009, 05:03 AM
Hi

I'm not sure exactly what you need or what you want to do, but it looks like you could implement your iterator as an internal class of IntSet. For example:-


class IntSet
{

public:

...
...
...

class iterator
{
public:
iterator() ;
iterator( const iterator & src ) ;

private:
index_ ;
} ;

iterator begin() ;
iterator end() ;

etc
}



IntSet::iterator::iterator()

: index_( -1 )
{
}


b e n

AlmostThere
Apr 8, 2009, 06:27 PM
. Me thinks something else is afoot, do I need to create an iterator class?

Not if you are going to use the std::vector iterator, which is what you are doing by using the typedef.

In your class you will have something like (and the same for consts):

class IntSet
{

typedef vector<int>::iterator iterator;

vector<int> set;

iterator begin() { return set.begin(); }
iterator end() { return set.end(); }

// ... rest of the implementation ...
};


What you need to do is write the interface for your set class (i.e. define the operations allowed). Then implement these using the vector<int>::iterator, as above, where I have assumed begin() and end() form the interface.

The catch is that you need to remember that you can do anything with that iterator that you can do with the vector iterator (e.g. allow you to set the value of the item via the iterator and end up with a non-unique set). This would obviously not be compatible with the behaviour of a set. You might like to prevent this by making every iterator const (or implementing your own iterator, but not both).

You would then provide methods such as add(int i) where you check the constraints of a set (i.e. unique values) before determining whether or not to add the item to the vector<int>, something like:

bool add(int i)
{
if (std::find(set.begin(), set.end(), i) != set.end()) return false;
set.push_back(i);
return true;
}