I'm making a special list and I came into a problem.
The linked list is special because it has sub levels. A cell in a list can include other cells.
The classes that I have are:
record - the cell container of the list that has an item.
rlist - the linked list
rlist::iterator - the iterator of the list
rlist and rlist::iterator are friends of record, and this is the problem that
arrises.
I have:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
class record {
public:
friendclass rlist;
friendclass rlist::iterator
...
}
class rlist {
public:
class iterator {
...
}
...
}
The compiler says about the line "friend class rlist::iterator":
use of undefined type 'rlist'
That doesn't solves the problem because rlist and rlist::iterator have to access to the elements of the record that isn't already defined. So this is what the compiler says in that case:
Hmm... A record doesn't really need to know what an iterator is. rlist needs to know record, and iterator needs to know rlist and record, but that's it.
And, you had to have "friend class rlist::iterator" in record which gave you "undefined type 'rlist'" since record needs to know rlist as well due to the nested class iterator.
One way to get around this is to make iterator a top level class such as rlistiterator and you can simply have "friend rlistiterator" in record without declaring any class first.
Otherwise, record needs to know rlist, rlist needs to know record, compiler will complain no matter which one is declared first.
There's no reason for Node to know that it belongs to a list. I could take this Node class and use it for a binary tree without making any changes to it.
Now, the iterator only need this information to work: the location of the current node, and the location of the next node. It would be initialized by passing a pointer to the list and it can figure out where the start of the list is.
Template is good, and std::list should be looked at first.
However, to simply get rid of dependency problem encountered, use encapsulation. record should only be accessed using its public interface/member methods. Use a friend only when no member method could achieve the same purpose.
Below is a piece of sample code. rlist needs not be a friend. The only friend is the non-member output operator which gives a "cout << record" syntax.
// This sample is by no means a complete list or iterator implemenation.
// It simply shows the idea how they may be implemented.
#include <ostream>
using namespace std;
class record {
private:
int id;
public:
record() : id(0) {}
record(int i) : id(i) {}
void operator<<(ostream &os) { os << id; }
friend ostream &operator<<(ostream &os, const record &r);
};
ostream &operator<<(ostream &os, const record &r)
{
os << r.id;
return os;
}