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.
Related
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);
}
I am always confused what is why we are using typedef struct node for creating node rather same thing can be easily implemented using struct node only...
That's not the way it is done.
it is usually
struct node { ... };
versus
typedef struct { ... } node;
//here node is a alias for an anonymous struct or...
typedef struct node_ { ... } node; //note the two names are different
In C++ that doesn't make any particular difference: node is in any case a type.
But it is different in C, where node is a tag for the type struct node (not just node) in the first case, and just the type node in the second case
Libraries defining types that have to work the same for both C and C++ usually adopt the second form, so that they can in any other expression to mention just node, instead of struct node, like in
node* first() { ... }
instead of
struct node* first() { ... }
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>.
I'm learning C++ and now I'm working with Template.
I'm trying to implement a Linked List:
ListElement.hpp
#ifndef LIST_ELEMENT_HPP_
#define LIST_ELEMENT_HPP_
template <class Type> class SingleLinkedList;
template <class Type>
class ListElement
{
public:
ListElement(const Type element);
~ListElement(void);
public:
Type val;
ListElement* next;
};
#endif
ListElement.cpp:
#include "ListElement.hpp"
ListElement<Type>::ListElement(const Type element)
{
*next = NULL;
val = element;
}
ListElement<Type>::~ListElement(void)
{
}
I'm getting an Error on ListElement.cpp releated to Type: Type is undefined.
I have found a lot of examples about how to implement a Linked List but none using a separated hpp and cpp.
Do you know how can I fix this error?
First problem:
You need to fix the way you are defining the member functions of your class template:
template<typename Type> // <== ADD THIS!
ListElement<Type>::ListElement(const Type& element)
// ^
// And perhaps also this?
// (don't forget to modify the
// corresponding declaration if
// you change it)
{
*next = NULL;
val = element;
}
Second problem:
You should move those definitions to the same header file that contains the definition of the class template, or the linker will complain about undefined references. For more information, see this Q&A on StackOverflow.
Third problem:
In your constructor, you are currently causing undefined behavior by dereferencing an uninitialized pointer. You shouldn't be doing:
*next = NULL;
^^^^^^^^^^^^^
Undefined Behavior! next is uninitialized and you are dereferencing it!
But rather:
next = NULL;
Or even better (using constructor initialization lists and C++11's nullptr):
template<typename Type>
ListElement<Type>::ListElement(const Type& element) :
val(element),
next(nullptr)
{
}
Firstly - in general you cannot split declaration and implementation of template class in different files.
Secondly - before implementation should be template decl.
template<typename Type>
ListElement<Type>::ListElement(const Type element)
{
next = NULL;
val = element;
}
At first try to add
template<class Type>
before each function in .cpp file
It wouldn't work. (Linker errors) So move all your implementation to .h file.
Then perhaps you should change
ListElement(const Type element);
to
ListElement(const Type &element);
I am making a tree of n children to store directories of computer. Now, concept is simply make a tree (that would not be a BT of course) and each node will have children as well. Consider the code below then I will explain the problem.
First Consider this:
C/users/DeadCoder/Movies/Batman.
Now In my main.cpp I have this all C, users, DeadCoder, Movies, Batman in a vector and then I send two pairs in insert Func. if root==NULL; it would just insert C. Next time C and users would go. It would find C and then insert users occordingly. Let's now see the code .
template <class T>
struct Node;
template <class T>
class tree
{
Node<T> *root;
public:
tree();
~tree();
int insert(T str, T str1);
Node<T> *getRoot();
Node<T> *search(T item, Node<T> *tempPtr);
};
template <class T>
struct Node{
T n;
Node<T> *sibling;
tree<T> children; // SEE my each node has children.
Node(T N){
this->n = N;
this->sibling = NULL;
}
};
// In .cpp FILE;
// Initilaizer
template <class T>
tree<T>::tree() // Constructor Initialization.
{
root=NULL;
}
// Insert Function.
template <class T>
int tree<T>::insert(T push, T find)
{
Node<T> *rPtr = root;
if (rPtr==NULL){
//ROOT is NULL. C needs to be inserted which is in find.
Node<T> *pusPtr = new Node<T>(find);
root = pushPtr;
root->sibling=NULL;
return 0;
}
else if(rPtr!=NULL){
Node<T> *pushPtr = new Node<T>(push);
Node<T> *temp2 = search(find, root);
Node<T> *temp = temp2->children.getRoot(); // say it LINE_40.
if (temp==NULL){
temp = pushPtr;
temp->sibling=NULL;
return 1;
}
// children are already present.
else if(temp!=NULL){
// You don't need to know code for this part.
}
}//if.
}
// Search Function.
template <class T>
Node<T> *tree<T>::search(T data, treeNode<T>* N)
{
if (N->n==data){ // where n represent directory.
return N; // data found.
}//if....
else{
Node<T> *child = N->children.getRoot();
// This is where i get Segmentation fault,
// because child is ==NULL; but you see in LINE_40 I did insert the child for C.
if(child!=NULL){ // say it line 80.
search(data, child);
}//if...
if(child->sibling!=NULL){
search(data, child->sibling);
}
}
}// search....
PROBLEM: C inserted. Users inserted. Now in search function at Line 80, it comes to find the child for C. and it should be Users as I have inserted it in LINE 40. BUT Instead it says child==NULL. I have been debugging for hours and I don't know why it says so. I hope Everybody gets the problem.
Now I really need to know why it is regarding C child to be NULL, It has to be users. Can anyOne see what is the problem???? HELP !!!!
Line 42 does nothing (I mean it has no side effect). It just puts a value in a temporary variable then leaves.
You probably want your temp to be a reference to the root. Something like: Node<T> *&temp =
Are you sure insert method actually inserted these elements?
It might be helpful to implement postconditions so to verify your methods actually fulfill their contract (design by contract).
This way you'll directly get what is wrong and debugging will be fast or unnecessary in some cases, since you'll get log messages saying "this method was supposed to do this but failed doing it", otherwise you'll look for hours where the problems comes from.