views:

1090

answers:

2

I'm trying to create an iterator class as a member-class for a list class, and am trying to overload the indirection operator (*) to access the list it's pointing to:

template<class T>
T list<T>::iterator::operator*(iterator& iter)
{
    return ((iter.lstptr)->current)->data;
}

where lstptr is a pointer to a list, current is a pointer to a node class, and the node class contains the data member data of type T.

Iterator is declared like this:

template<class T>
class list
{
public:
class iterator;
};

template<class T>
class list<T>::iterator
{
//stuff
};

I am able to compile the function definition of the overloaded operator* fine, but when I try to do something like:

list<int> lst1;
lst1.add(6);
list<int>::iterator IT;
IT = lst1;
//everything above this point compiles fine
int a = *IT; //error here (line fourteen)

The error I get says <1> that I am using an illegal indirection, and <2> that it cannot convert from list::iterator to int. Both errors occur on line fourteen.

Does anybody know what I am doing wrong and how I can overload the indirection operator correctly?

NB: If you need to see more code, tell me which part, because I don't want to put th entire code up here because it's abot 205 lines, and 204 of those lines don't (I think) have any errors.

+5  A: 

You overloaded the multiply operator. Take the parameter out to make it an indirection operator.

template<class T>
T list<T>::iterator::operator*()
{
    return ((this->lstptr)->current)->data;
}

You should also have it return a reference if you want code like *IT = 3; to compile.

template<class T>
T& list<T>::iterator::operator*()
{
    return ((this->lstptr)->current)->data;
}
Shmoopty
It's not the multiply operator! But you're correct about returning a reference.
Zifre
He should write the operator* as a free function for it being the indirection operator. As it was written by the OP, it's the multiplication operator. I actually overlooked it too, totally ignoring the fact that it's apparently declared as a member :)
Johannes Schaub - litb
Keand64
Just put all that stuff into iterator and write T operator*() { return ((this->lstptr)->current)->data; } no need to defined it out-of-class. You will need to define it within the header anyway since it's a member of a template.
Johannes Schaub - litb
@Keand64: I edited the answer to clarify.
Shmoopty
Good catch Shmoopty!
j_random_hacker
+3  A: 

You have two problems here; the first is that you have accidentally overloaded the multiplication operator and not the dereferencing operator; the second is that you haven't returned a reference type.

The first issue comes about as a result of the number of parameters. Every non-static member function of a class has an additional "hidden" parameter: this. this is, of course, the pointer to the object the function is being invoked on. As a result, you have actually declared a version of the operator taking two parameters. By removing the second iterator parameter and operating on this, you will be overloading the unary * and not the binary one.

The second issue is a minor one of return type; you are returning a copy to the original object and not the original object itself. Declare the return type as T& to return a reference.

coppro
+1. Regarding return type, it *may* be preferable to just return a copy as the OP is doing if the underlying type is a small value type and it's not intended to be assignable -- but that would be an unusual case. Prefer a ref as coppro suggests.
j_random_hacker