Nested class pointer access - c++

i am rather new to c++ and in my attempt to create a linked list i have run into an error which i do not understand.
the code:
template <typename T>
class List{
class Node{
T data;
Node<T> *next;
Node<T> *previous;
Node<T>(T& data,const Node<T> *next,const Node<T> *previous): data(data),
next(next),previous(previous){
};
};
Node<T> *head;
Node<T> *tail;
int size;
public:
class Iterator{
Node<T> *node;
List<T> *list;
};
void List<T>::remove(List<T>::Iterator& It){
if(It.list!=this){ // FIELD list COULD NOT BE RESOLVED
throw NON_MATCHING_LIST();
}
if(size==0 || It.node=tail){ //FIELD node COULD NOT BE RESOLVED
throw ELEMENT_NOT_FOUND();
}
It.node->previous=It.node->next; //FIELD node COULD NOT BE RESOLVED (and naturally the rest).
It.node->next->previous=It.node->previous
}
};
in my remove function, i am trying to remove the member of the list that came right before the iterator, alas i am getting an error saying
node/list fields could not be resolved
i have tried passing the iterator as type Iterator& or Iterator, neither have worked.
Would appreciate any feedback.

Apart from issues that others have mentioned in the comments to the question, it seems your (first) problem is that you need to use the typename disambiguator:
typename List<T>::Iterator
// ^^^^^^^^
This tells the compiler that it should parse Iterator as the name of a type, rather than the name of a data member of List<T>.

Related

Return struct in class template function

I'm learning C++ with some exercises from a book that I found a while ago. My task is described below and I've tried to find a work around for returning a template node I created for the template function getLastNode to add a node at the end of the list. Is it possible to do that, currently I can't find a way to let's call it explain the compiler what TNode is as a struct within a class return value.
I might have the best way to declare nodes in this code. Perhaps, a struct within a class can complicate class template methods implementations. Do you feel there's another strategy? Please let me know
Cheers!
/* Implement the data structure dynamic doubly linked list (DoublyLinkedList<T>) - list,
* the elements of which have pointers both to the next and the previous elements. Implement
* the operations for adding, removing and searching for an element, as well as inserting
* an element at a given index, retrieving an element by a given index and a method, which returns an array with the elements of the list*/
#include <iostream>
template<typename TValue>
class List{
struct TNode{
TValue value;
TNode *previous;
TNode *next;
}Node;
public:
List();
~List();
void addNode(TValue);
private:
TNode *root;
TNode getLastNode(TNode);
};
template<typename TValue>
List<TValue>::List():root(0) {}
template<typename TValue>
List<TValue>::~List<TValue>(){
}
template<typename TValue>
TNode List<TValue>::getLastNode(TNode node){
if(node.next==nullptr)
return node;
else
getLastNode(node.next);
}
template<typename TValue>
void List<TValue>::addNode(TValue value){
const TNode last = getLastNode(root);
last.next = Node;
last.next->value = value;
}
int main(){
List<int> test;
return 0;
}
To return TNode for the getLastNode method I had to add auto to its class method declaration.
Credits: #JaMiT
template<typename TValue>
auto List<TValue>::getLastNode(TNode node){
if(node.next==nullptr)
return node;
else
getLastNode(node.next);
}

C++ templates with various types based on input

I know there are many questions about that issue but nothing seems to work for me or it's too complex for me to understand.
So I have template Node
template <typename T>
class Node {
public:
T value;
Node* right;
Node* left;
Node(T value, Node<T>* right, Node<T>* left);
};
And Tree
template <typename T>
class Tree {
public:
Node<T>* root;
Tree();
~Tree() {}
void insert(T value);
Node<T>* search(T value, Node<T>* root) noexcept(false);
};
Now I want to create different Tree templates basing on what the user chose. Users can choose int, double, or string, these are the only options. I tried to use base class solution but my problem is that Tree uses type T in functions (and in Node) so I don't know how I should declare them in, let's call it BaseTree. Then I would be able to something like this:
BaseTree* tree;
tree = new Tree<int>();
I'm looking for a simple solution, I'm sort of beginner and it surprises me how this simple issue is so difficult for me to solve.
The solution is to templatize the generic functions also. Let's say you have something like this in mind:
void traverse(BaseTree const& tree) noexcept {
/* Logic here */
}
Instead, you do:
template<typename T>
void traverse(Tree<T> const& tree) noexcept {
/* Logic here */
}
This also helps that you can use Node<T> to refer to the node instead of fabricating BaseNode and whatnot again.

How to access a structure declared inside of a class?

I have linked list class that implements a node structure, like this:
template<class T>
class LinkedList
{
public:
struct Node {
T value;
Node *next;
};
int Length;
Node *head;
Node *tail;
LinkedList() {
Length = 0;
Node* head = nullptr;
Node* tail = nullptr;
}
};
I tried accessing the node Node structure from the driver file like so:
#include "LinkedList.h"
template<class T>
void foo(LinkedList<T> list) {
LinkedList<T>::Node* a = list.head; // does not work
LinkedList<int>::Node* b = list.head; // works (if T is int of course)
}
Using a template T does not work (it gives me "identifier not found" error message), while directly specifying the correct datatype works. Why is that? Is there a way to avoid the error?
Use typename LinkedList<T>::Node* a = ...
The problem is that not knowing what exactly T is, the compiler can’t be sure LinkedList<T>::Node is indeed a type (LinkedList could be specialized for T so the definition doesn’t help). You need to instruct it to treat it that way.

Error: binding to reference of type discards qualifiers

I am so sorry, I know this has been asked before, but even if I tried reading all the other answers to similar questions I can't understand my error.
I am using Eclipse, I am programming in C++ and I am trying to make a linked list using templates.
I am using a node class that will be useful for my linked list, and I have this function specification:
template <class item>
void list_insert(node<item>*& head, const item&e);
Allright. I want to use this function SO in my list class I can have this:
template <class item>
class list{
public:
list(){head=NULL;}
void set_head(node<item>*h){head=h;}
node<item>*& get_head(){return head;}
const node<item>* get_head()const{return head;}
bool empty()const{return head==NULL;} // is the list empty?
void insert(const item&e){list_insert(head,e);} //ERROR GETS HERE!
void print(); // print the list clockwise
void printback(); //print it counterclockwise
private:
node<item>* head;
};
I do that so I can implement list_insert like this:
template <class item>
void list_insert(node<item>*& head, const item& e){
head= new node<item>(e,head);
}
Now, in this last piece of code I get this error:
error: binding 'const int' to reference of type 'int&' discards qualifiers
I have read that basically the compiler is telling me ''ehi, if you do that, the const condition you wanted will be violated, so I give you an error'', allright, but still I don't understand the actuall error, or, anyway, what is the reasoning behind it.
Also because I am supposed to do a counterclockwise insert function too, but I am having troubles with the clockwise actually, so I am pretty stuck.
Thank you so much in advance.
EDIT: I am so sorry I did not provide actual example of what I am doing.
Basically, I am trying to make a linked list - simply and basic for my exam.
My linked-list is basically a stack made of nodes. Nodes are the component of my list, that are made of a data part and a link to the next node part:
template <class item>
class node{
public:
//CONSTRUCTOR
nodo(item & d=item(), nodo*l=NULL){
data=d;
link=l;
}
//GET E SET METHODS
void set_data(item& d){data=d;}
void set_link(node*l){link=l;}
item& get_data(){return data;}
const item& get_data()const{return data;}
node*& get_link(){return link;}
const node* get_link()const{return link;}
private:
item data;
node* link;
};
Now, as said my list is made of nodes and in the private part I declared a pointer to the head of the list.
node<item>* head;
That is the example of this code-- and then the problem occurs as I wrote before.
In the constructor of node you should pass item by const-reference (and there is some typo, perhaps a copy+paste error in your node class.
class node{
public:
//CONSTRUCTOR
node(item const & d=item(), node*l=0)
: data(d), link(l) // prefer initializer list here
{ }
//...

Templates and access

I've read tons of guides of how to use templates effectively, however none seem to answer this question. They all seem to access the nodes inside the class and nothing more.
For example, I have a doubly linked list. The list contains a Node:
template<class T>
struct TNode
{
T Data;
TNode* pNext;
TNode* pPrev;
};
Now I'm trying to make the data accessible from anywhere, for example:
TNode* pNode = m_VertexList.GetFirstElement();
However every way I've tried, I end up having to cast it in some way:
TNode<CObject*>* pNode = m_VertexList.GetFirstElement<CObject*>();
//I can't remember at this point if this is the exact syntax, but you get the idea
Now while this isnt a very big problem, it isn't ideal
Is there a way I can make it so the first line will correctly return the type without having to specify it?
Here is the error I get:
1>...error C2955: 'TNode' : use of class template requires template argument list
Here in pastebin is the whole node structure and dllist class:
http://pastebin.com/awkq9rcq
Any help would be appreciated :)
You would need something like auto node = m_VertexList.GetFirstElement(); because m_VertexList should be a class template. But you can add a typedef for the node to the list class and use that too:
template <typename T>
struct List
{
typedef Node<T> node_type;
typedef Node<T>* node_ptr_type;
node_ptr_type GetFirstElement() { return first_; }
node_ptr_type first_;
....
};
then
typedef List<Cobject> CObjectList
CObjectList l;
auto n0 = l.GetFirstElement();
CObjectList::node_ptr_type n1= l.GetFirstElement();
Once you're done with this exercise, you may want to look at std::list for an example of a well implemented doubly linked list class template.