Reputation: 25
This is my LinkedList namespace
namespace LinkedList {
template<class T>
class Node{
public:
Node(const T& data)
:data_(data), next_(nullptr) {}
T data_;
Node<T> *next_;
Node<T> *operator++(){
return next_;
}
};
template<class T>
class LinkedList{
public:
LinkedList()
: head_(nullptr), tail_(nullptr) {}
~LinkedList(){
Node<T> *curr = head_;
Node<T> *next;
while(curr != nullptr){
next = curr->next_;
delete curr;
curr = next;
}
}
void Append(const T& data) {
Node<T> *tmp = new Node<T>(data);
if(head_ == nullptr) {
head_ = tmp;
tail_ = tmp;
} else if(head_ == tail_){
head_->next_ = tmp;
tail_ = tmp;
} else {
tail_->next_ = tmp;
tail_ = tmp;
}
}
void Present(){
for(Node<T> *curr = head_; curr != nullptr; curr=curr->next_){
std::cout << curr->data_ << std::endl;
}
}
Node<T> *begin(){
return head_;
}
Node<T> *end(){
return nullptr;
}
private:
Node<T> *head_;
Node<T> *tail_;
};
}
I was reading into Iterators and wanted to make my LinkedList object compatible with range based for loops. This is what I got from reading about range-based for loops
for(auto x: list){ }
is equivalent to
for(; begin != end; ++begin) { //*begin};
I thought I was being cheeky and could skip a couple steps of operator overloading (!=, *) for my LinkedList to work with range based for loops by programming my iterator into my Node class for no other reason besides that I felt like it. This is only my second day of learning C++ so this might be a stupid question but I am still a little confused on why this doesn't work:
LinkedList::LinkedList<int> list;
list.Append(3);
list.Append(5);
for(auto x: list) { //blah blah blah}
I know that my prefix increment is the core issue, when the for loop does ++__begin, what I am hoping it does is ___begin=_begin->next however it does not. Why is this? How the operator overloading works in my mind is is that whatever member variables I reference in the overloading function, it is referencing from the instance I am operating on. And when I return the ptr, it is setting whatever instance I am operating on to this ptr. I know my understanding of this is wrong because it doesn't work, so please someone explain to me how it actually works lol.
Upvotes: 0
Views: 64
Reputation: 67713
You've written a
template<class T>
Node<T>* Node<T>::operator++();
which would get invoked like
Node<int> n;
Node<int> *p = ++n; // calls the pre-increment operator
Note this is quite different to the canonical form
Node<T>& Node<T>::operator++();
which returns a reference to the incremented object that you can use in an expression.
But there's another problem: operator overloading works
When an operator appears in an expression, and at least one of its operands has a class type or an enumeration type, ...
But Node<T>*
is not a class type. It's a pointer, and pointers already have their own built-in operators. You can't overload them. There is no Node<T>*::operator++()
.
Write an iterator. It's not that bad, and they actually work!
NB. Iterators are designed to generalize pointers, and to have a compatible interface. You can use raw pointers if your container is basically an array - because incrementing a pointer is already the right way to iterate over an array.
It's only when we want to provide array-like or pointer-like access to a non-contiguous structure that we have to do this extra work.
Upvotes: 1