I must to do a list of template abstract base classes (and I have the delivered classes too)
but I don't can inizialize the element of my list because the element is an abstract class...
this is my declaration:
/* fsm (list node) declaration */
template<class step_type> class fsm {
protected:
step_type step;
step_type step_old;
step_type step_tmp;
char name[256];
fsm *next;
fsm *prev;
public:
fsm(step_type step);
virtual void update() = 0;
void show(){cout << step << ' ' << step_tmp << '\n'; };
void init(step_type st_current) {step = st_current;};
//metodi per gestione nodo lista
step_type getStep() { return step; }
fsm* getNext() { return next; }
fsm* getPrev() { return prev; }
void setStep(step_type s) { step = s; }
void setNext(fsm *n) { next = n; }
void setPrev(fsm *p) { prev = p; }
};
/* fsm_List declaration */
template <class step_type>
class fsm_List
{
fsm<step_type> *head, *tail;
int size;
public:
fsm_List();
fsm<step_type>* getHead() { return head; }
fsm<step_type>* getTail() { return tail; }
int getSize() { return size; }
void insert(fsm<step_type> *n); // add node to list
void insert(step_type &value); // new node and add in list
fsm<step_type> *search(step_type &value); //first node with value
void delnode(fsm<step_type> *n); // remove node
int delvalue(step_type &value); // remove all nodes
};
this is my delivered class:
class deri_pinza : public fsm<pin_steps>{
private:
bool cmd_prelevamento_done;
public:
deri_pinza(): fsm<pin_steps>(ST_PIN_BOOT){
cmd_prelevamento_done = false;
};
void update();
};
where:
enum pin_steps {
ST_PIN_BOOT,
ST_PIN_CHECK_MOTORE,
ST_PIN_ZERO_MOTORE,
ST_PIN_WAIT_ZERO_MOTORE,
ST_PIN_OPEN,
ST_PIN_READY,
};
I have tryed to test in my main, but it's wrong...
fsm<pin_steps> *one, *two, *three, *four, *five;
one = new fsm<pin_steps>(ST_PIN_CHECK_MOTORE);
two = new fsm<pin_steps>(ST_PIN_ZERO_MOTORE);
three = new fsm<pin_steps>(ST_PIN_WAIT_ZERO_MOTORE);
four = new fsm<pin_steps>(ST_PIN_OPEN);
five = new fsm<pin_steps>(ST_PIN_READY);
fsm_List<pin_steps> *mylist = new fsm_List<pin_steps>();
(*mylist)+=(*one);
(*mylist)+=(*two);
mylist->insert(one);
mylist->insert(two);
cout << *mylist << endl;
how can I inizialize the List without inizialize fsm ( abstract class)?
you can't create an instance of fsm<> with new, since it's abstract - it contains the pure virtual method virtual void update()=0;
you can for example:
fsm<pin_steps> *one...
one = new deri_pinza;
this is legal - and go on from here...
EDIT - followup to our comments:
if you need a more general deri pinza (a generic one), it can be defined as:
template <typename STEP_TYPE>
class deri_pinza_gen : public fsm<STEP_TYPE> {
private:
bool cmd_prelevamento_done;
public:
deri_pinza_gen(STEP_TYPE step) : fsm<STEP_TYPE>(step){
cmd_prelevamento_done = false;
};
virtual void update();
virtual ~deri_pinza_gen();
};
and then:
mylist->insert( new deri_pinza_gen<pin_steps>(ST_PIN_BOOT) );
mylist->insert( new deri_pinza_gen<pin_steps>(ST_PIN_CHECK_MOTORE) );
ANOTHER_list->insert( new deri_pinza_gen<ANOTHER_pin_steps>(ANTHER_enum_item) );
...
are valid insertions. I have declared update() virtual here, so you can derive your deri_pinza from this one, if you need it.
Related
Where am I going wrong in constructing my LinkedList class?
I've re-declared the pure-virtual methods from IList in your LinkedList class, but LinkedList seems to be getting treated like an abstract class and so the compiler doesn't seem to allow me to create a LinkedList object in my main function:
main.cpp
#include <iostream>
#include <string>
#include "LinkedList.h"
using namespace std;
int main()
{
int A[] {1, 2, 3, 4, 5};
LinkedList l(A, 5);
cout << l.getCurrentSize()<<endl;
l.display();
return 0;
}
LinkedList.h
#ifndef LINKED_LIST_
#define LINKED_LIST_
#include "IList.h"
class LinkedList : public IList
{
protected:
struct Node
{
int data;
struct Node* next;
};
struct Node* first;
public:
// constructor
LinkedList() { first = nullptr; }
LinkedList(int A[], int n);
// accessors void display();
virtual int getCurrentSize();
//destructor
virtual ~LinkedList();
};
#endif
LinkedList.cpp
#include <iostream>
#include <string>
#include "LinkedList.h"
using namespace std;
// constructor
LinkedList::LinkedList(int A[], int n)
{
Node* last, * t;
int i = 0;
first = new Node;
first->data = A[0];
first->next = nullptr;
last = first;
for (i = 1; i < n; i++)
{
t = new Node;
t->data = A[i];
t->next = nullptr;
last->next = t;
last = t;
}
};
// destructor
LinkedList::~LinkedList()
{
Node* p = first;
while (first) {
first = first->next;
delete p;
p = first;
}
}
void LinkedList::display()
{
Node* p = first;
while (p)
{
cout << p->data >> " ";
p = p->next;
}
cout << endl;
}
int LinkedList::getCurrentSize() const
{
Node* p = first;
int len = 0;
while (p)
{
len++;
p = p->next;
}
return len;
}
IList.h
// Modified from code created by Frank M. Carrano and Timothy M. Henry.
// Copyright (c) 2017 Pearson Education, Hoboken, New Jersey.
#ifndef I_LIST_
#define I_LIST_
class IList
{
public:
/** Constructor */
IList () : traverseCount(0) { }
/** Destroys object and frees memory allocated by object.
(See C++ Interlude 2) */
virtual ~IList () { }
/** Gets the current number of entries in this list.
#return The integer number of entries currently in the list. */
virtual int getCurrentSize() const = 0;
/** Sees whether this list is empty.
#return True if the list is empty, or false if not. */
virtual bool isEmpty() const = 0;
/** Adds a new entry to this list.
#post If successful, newEntry is stored in the list and
the count of items in the list has increased by 1.
#param newEntry The object to be added as a new entry.
#return True if addition was successful, or false if not. */
virtual bool add(int newEntry) = 0;
/** Removes one occurrence of a given entry from this list,
if possible.
#post If successful, anEntry has been removed from the list
and the count of items in the list has decreased by 1.
#param anEntry The entry to be removed.
#return True if removal was successful, or false if not. */
virtual bool remove(int anEntry) = 0;
/** Removes all entries from this list.
#post List contains no items, and the count of items is 0. */
virtual void clear() = 0;
/** Tests whether this list contains a given entry.
#param anEntry The entry to locate.
#return True if list contains anEntry, or false otherwise. */
virtual bool contains(int anEntry) = 0;
/** Get the count of number of nodes traversed.
#return The integer number of nodes traversed since last time the count was reset. */
virtual int getTraverseCount() const { return traverseCount; }
/** Reset the count of nodes traversed to zero. */
virtual void resetTraverseCount() { traverseCount = 0; }
protected:
int traverseCount;
}; // end IList
#endif
Your IList is an abstract class with six pure virtual member functions. In order to create the instance of the derived one (i.e. LinkedList) you need to implement those functions inside the child as well.
class LinkedList : public IList
{
// ..... other members
public:
// ..... other members
virtual int getCurrentSize() const override;
bool isEmpty() const override { // implementation }
bool add(int newEntry) override {// implementation }
bool remove(int anEntry) override { // implementation }
bool contains(int anEntry) override { // implementation }
void clear() override { // implementation}
};
Also recommended using the override specifier to override the virtual functions from the base class, so that both the compiler and the reader can easily recognize them, without looking into to the base.
Other Issues:
Also note that your getCurrentSize() functions declaration in the child class (i.e. LinkedList) lacks a const.
Typo at cout << p -> data >> " "; should be cout << p->data << " ";
Why is "using namespace std;" considered bad practice?
Here is a simple c++ class for binary tree. Compiler throws an error:
E0147 declaration is incompatible with "void BinaryTree::getLeftChild(node *n)"
Here node is a struct defined under the private section in the class. I am not sure why it says incompatible declaration.
//------------------------ BinaryTree class-----------------
class BinaryTree
{
public:
BinaryTree();
~BinaryTree();
void createRootNode();
void getChildren();
void getLeftChild(node* n);
void getRightChild(node* n);
private:
typedef struct node
{
node *lchild = nullptr;
int data;
node *rchild = nullptr;
}node;
queue <node*> Q;
node *root;
};
BinaryTree::BinaryTree()
{
createRootNode();
getChildren();
}
void BinaryTree::createRootNode()
{
root = new node();
cout << "Enter value for root node" << endl;
cin >> root->data;
Q.push(root);
}
void BinaryTree::getChildren()
{
while (Q.empty == false)
{
getLeftChild(Q.front());
getRightChild(Q.front());
Q.pop();
}
}
void BinaryTree::getLeftChild(node* n)
{
}
void BinaryTree::getRightChild(node* n)
{
}
Code picture with errors
I got another struct in global scope declared as "node" which created chaos. Secondly, i also need to fix the order of public and private sections.
Here is working code
//------------------------ BinaryTree class-----------------
class BinaryTree
{
private:
typedef struct node
{
node *lchild = nullptr;
int data;
node *rchild = nullptr;
}node;
queue <node*> Q;
node *root;
public:
BinaryTree();
~BinaryTree();
void createRootNode();
void getChildren();
void getLeftChild(node* n);
void getRightChild(node* n);
};
BinaryTree::BinaryTree()
{
createRootNode();
getChildren();
}
void BinaryTree::createRootNode()
{
root = new node();
cout << "Enter value for root node" << endl;
cin >> root->data;
Q.push(root);
}
void BinaryTree::getChildren()
{
while (Q.empty() == false)
{
getLeftChild(Q.front());
getRightChild(Q.front());
Q.pop();
}
}
void BinaryTree::getLeftChild(node* n)
{
}
void BinaryTree::getRightChild(node* n)
{
}
First error, is that you need to forward declare the node.
Second error, is that you are trying to access node which is privately declared inside of BinaryTree.
First answer:
typedef struct node
{
node* lchild = nullptr;
int data;
node* rchild = nullptr;
}node;
class BinaryTree
{
public:
BinaryTree();
~BinaryTree();
void createRootNode();
void getChildren();
void getLeftChild(node* n);
void getRightChild(node* n);
private:
node* root;
};
void BinaryTree::getLeftChild(node* n)
{
}
void BinaryTree::getRightChild(node* n)
{
}
Now code compiles fine.
Or if you want to have the typedef defined as private inside, you need the implementation to be inside the class as well.
Second Answer:
typedef struct node;
class BinaryTree
{
public:
BinaryTree();
~BinaryTree();
void createRootNode();
void getChildren();
void getLeftChild(node* n)
{
}
void getRightChild(node* n)
{
}
private:
typedef struct node
{
node* lchild = nullptr;
int data;
node* rchild = nullptr;
}node;
node* root;
};
We have an assignment to create a Binary Search Tree with some basic functions. I feel I'd be capable of scraping by if it weren't for the files included with the assignment that we need to adhere to in order for the graders to implement our code with their grading program. Students are given a file called "Factory.cpp" which has a function that attempts to return an object of "BinarySearchTree" (return new BinarySearchTree();). However, VS 2013 gives me the error seen in the title. After some research, I can't find any infomration I can implement into my own problem to get rid of the error. Template classes are obviously more abstract and I can't find out what to include/leave out, etc to make things work.
The following is my incomplete code I have so far in my BinarySearchTree.h:
#pragma once
#include "BSTInterface.h"
#include "NodeInterface.h"
#ifndef BINARY_SEARCH_TREE_H
#define BINARY_SEARCH_TREE_H
struct BTNode :public NodeInterface{
// Data Fields
int data;
BTNode* left;
BTNode* right;
// Constructor
BTNode(const int& the_data,
BTNode* left_val = NULL,
BTNode* right_val = NULL) :
data(the_data), left(left_val), right(right_val) {}
// Destructor (to avoid warning message)
virtual ~BTNode() {}
// Interface Functions
int getData(){
return data;
}
NodeInterface* getLeftChild(){
return left;
}
NodeInterface* getRightChild(){
return right;
}
}; // End BTNode
#include <sstream>
template<class T>
class BinarySearchTree:public BSTInterface
{
public:
BTNode* root;
// BST Constructor / Deconstructor
BinarySearchTree() : root(NULL){}
//BinarySearchTree(const int& the_data,
// const BinarySearchTree& left_child = BinarySearchTree(),
// const BinarySearchTree& right_child = BinarySearchTree()) :
// root(new BTNode(the_data, left_child.root, right_child.root)){}
virtual ~BinarySearchTree(){}
// Interface Functions ----------------------
NodeInterface* getRootNode(){
return root;
}
bool add(int data){
return addRec(root, data);
}
bool addRec(BTNode* &x, int data){
if (x == NULL){
if (Search(root, data) == true){
return false;
}
else{
root = GetNewNode(data);
return true;
}
}
if (data == x->data){
return false;
}
if (x != NULL){
if (data < x->data){
return addRec(x->left, data);
}
if (data > x->data){
return addRec(x->right, data);
}
}
}
bool remove(int data){
return false;
}
bool removeRec(BTNode* &x, int data){
return false;
}
void clear(){
}
// ------------------------------------------
// My Functions -----------------------------
BTNode* GetNewNode(int data){
BTNode* newNode = new BTNode();
newNode->data = data;
newNode->left = newNode->right = NULL;
return newNode;
}
bool Search(BTNode* root, int data) {
if (root == NULL) {
return false;
}
else if (root->data == data) {
return true;
}
else if (data < root->data) { // had <= instead
return Search(root->left, data);
}
else if (data > root->data) { // had no "if"
return Search(root->right, data);
}
}
// ------------------------------------------
};
#endif
Which is derived from the following 2 "Interface" files:
NodeInterface.h:
//YOU MAY NOT MODIFY THIS DOCUMENT
#pragma once
#include <iostream>
class NodeInterface {
public:
NodeInterface() {}
virtual ~NodeInterface() {}
/*Returns the data that is stored in this node*/
virtual int getData() = 0;
/*Returns the left child of this node or null if it doesn't have one.*/
virtual NodeInterface * getLeftChild() = 0;
/*Returns the right child of this node or null if it doesn't have one.*/
virtual NodeInterface * getRightChild() = 0;
};
BSTInterface.h
//YOU MAY NOT MODIFY THIS DOCUMENT
#pragma once
#include "NodeInterface.h"
using namespace std;
class BSTInterface {
public:
BSTInterface() {}
virtual ~BSTInterface() {}
//Please note that the class that implements this interface must be made
//of objects which implement the NodeInterface
/*Returns the root node for this tree*/
virtual NodeInterface * getRootNode() = 0;
/*Attempts to add the given int to the BST tree*/
virtual bool add(int data) = 0;
/*Attempts to remove the given int from the BST tree*/
virtual bool remove(int data) = 0;
/*Removes all nodes from the tree, resulting in an empty tree.*/
virtual void clear() = 0;
};
Then they give us "Factory.h" and "Factory.cpp," which I believe they use to grab our BinarySearchTree from in order to grade using their grading program:
Factory.h:
#include "BSTInterface.h"
using namespace std;
/*
WARNING: It is expressly forbidden to modify any part of this document, including its name
*/
class Factory
{
public:
static BSTInterface * getBST();
};
Factory.cpp:
#include "Factory.h"
#include "BinarySearchTree.h"
//You may add #include statements here
/*
You will MODIFY THIS DOCUMENT.
getBST()
Creates and returns an object whose class extends BSTInterface.
This should be an object of a class you have created.
Example: If you made a class called "BinarySearchTree", you might say, "return new BinarySearchTree();".
*/
BSTInterface * Factory::getBST()
{
return new BinarySearchTree();//Modify this line
}
In "Factory.cpp", BinarySearchTree is marked as an error in VS with the message "argument list for class template is missing." How do I fix this? Along with any other errors you see.
Also, how would I declare a new BinarySearchTree object in a main() and call its functions in order to test it?
For that error, in these lines:
template<class T>
class BinarySearchTree:public BSTInterface
{
just get rid of the first line. That line is telling the compiler that you BinarySearchTree class is a template class. But since your class uses an int for data it would seem that is not needed.
I haven't looked at your other code so I won't comment on anything else.
I'm new to C++. I'm trying to implement a LinkedList, for which I created two classes Node and LinkedList.
I created some test functions. One to test the Node creation and another to test the isEmpty function from LinkedList. However, when I try to test them. What's created in 'testNode()ends up being in the same Node I create insideLinkedListashead`.
This may be trivial question, however as a newcomer to C++ this concept is still no clear to me. I'd like to know why it is referring to the same instance created previously.
#include <iostream>
#include <assert.h>
using namespace std;
class Node
{
private:
int data;
int next;
public:
int getData(){return data;}
void setData(int new_data) {data = new_data;}
int getNext(){return next;}
void setNext(int new_next) {next = new_next;}
};
class LinkedList
{
Node head;
Node head2;
public:
bool isEmpty()
{
if (head.getData() == 0) {return true;}
return false;
}
};
void testNode()
{
Node aNode;
aNode.setData(15);
aNode.setNext(23);
assert (aNode.getData() == 15);
assert (aNode.getNext() == 23);
}
void testEmptyLinkedList()
{
LinkedList ll;
assert (ll.isEmpty() == true);
}
Initialize your data.
int data = 0;
int next = 0;
Live On Coliru
#include <iostream>
#include <cassert>
using namespace std;
class Node {
private:
int data = 0;
int next = 0;
public:
int getData() { return data; }
void setData(int new_data) { data = new_data; }
int getNext() { return next; }
void setNext(int new_next) { next = new_next; }
};
class LinkedList {
Node head;
Node head2;
public:
bool isEmpty() {
if (head.getData() == 0) {
return true;
}
return false;
}
};
void testNode() {
Node aNode;
aNode.setData(15);
aNode.setNext(23);
assert(aNode.getData() == 15);
assert(aNode.getNext() == 23);
}
void testEmptyLinkedList() {
LinkedList ll;
assert(ll.isEmpty() == true);
}
int main() {
testEmptyLinkedList();
}
If your intention is to implement LinkList, each node of the list should contain the address of the next one.
So "next" shoud be declared as a pointer to a Node. Same for the first node of the list.
class Node {
private:
int data;
Node *next;
....
};
class LinkedList {
private:
Node *head;
...
};
I have been struggling for too long a time now with a rather simple question about how to create a generic linked list in c++. The list should be able contain several types of structs, but each list will only contain one type of struct. The problem arises when I want to implement the getNode() function [see below], because then I have to specify which of the structs it should return. I have tried to substitute the structs with classes, where the getNode function returns a base class that is inherited by all the other classes, but it still does not do the trick, since the compiler does not allow the getNode function to return anything but the base class then.
So here is some code snippet:
typedef struct struct1
{
int param1;
(...)
} struct1;
typedef struct struct2
{
double param1;
(...)
} struct2;
typedef struct node
{
struct1 data;
node* link;
} node;
class LinkedList
{
public:
node *first;
int nbrOfNodes;
LinkedList();
void addNode(struct1);
struct1 getNode();
bool isEmpty();
};
LinkedList::LinkedList()
{
first = NULL;
nbrOfNodes = 0;
}
void LinkedList::addNode(struct1 newData)
{
if (nbrOfNodes == 0)
{
first = new node;
first->data = newData;
}
else
{
node *it = first;
for (int i = 0; i < nbrOfNodes; i++)
{
it = it->link;
}
node *newNode = new node;
newNode->data = newData;
it->link = newNode;
}
nbrOfNodes++;
}
bool LinkedList::isEmpty()
{
return !nbrOfNodes;
}
struct1 LinkedList::getNode()
{
param1 returnData = first->data;
node* deleteNode = first;
nbrOfNodes--;
if (nbrOfNodes)
first = deleteNode->link;
delete deleteNode;
return returnData;
}
So the question, put in one sentence, is as follows: How do I adjust the above linked list class so that it can also be used for struct2, without having to create a new almost identical list class for struct2 objects? As I said above, each instance of LinkedList will only deal with either struct1 or struct2.
Grateful for hints or help
There is already a generic link list available in C++, std::list. It will definitely be more efficient & should suffice for your usage.
If you still want to create your own generic link list
You should consider using templates and create a template implmentation of link list.
In c, where templates are not available the data node is stored in the form of a void* pointer. It takes advantage of the fact that a void pointer can point to any generic data type, You might consider that approach as well.
Basic tempaltes are easy.
Just declare the class as template with a templated type variable.
Now everywhere you have the declare type which you want to be generic, in the class, replace the explicit type name with the templated variable name.
For example, in your code, you want struct1 to be generic, so we replace it with T:
template<class T>
class LinkedList {
public:
node *first;
int nbrOfNodes; LinkedList();
void addNode(T);
T getNode();
bool isEmpty();
};
The STL source would be a piece of code to study.
You could also try https://github.com/simonask/ftl/blob/master/list.hpp
Both use templates, which should be understood to be able to make any generic classes.
Here is a generic implementation without using STL. You can create a templated class with a generic type and instantiate the singly_linked_list.
namespace api
{
template <typename T>
class i_list
{
public:
i_list() = default;
virtual ~i_list(){}
/* Add to front*/
virtual int push_front(T t_value) = 0;
/* Return the front item*/
virtual T top_front() = 0;
/* Remove and return the front elenment */
virtual T pop_front() = 0;
/* Add to the back */
virtual int push_back(T t_value) = 0;
/* Returns the back item */
virtual T top_back() = 0;
/* Removes and returns the back item */
virtual T pop_back() = 0;
/* Is key in the list */
virtual bool find(T t_value) = 0;
/* Remove the key from the list */
virtual int erase(T t_value) = 0;
/* Erases the entire list */
virtual void erase_all() = 0;
/* Is the list empty */
virtual bool empty() = 0;
/* return the size of the list */
virtual size_t size() = 0;
};
}
namespace list
{
template<typename T>
struct node
{
T m_data;
node* m_next;
node* m_jump;
int m_order;
node(T t_data) : m_data(t_data), m_next(nullptr) , m_jump(nullptr), m_order(-1){}
};
template<typename T>
class singly_linked_list : public api::i_list<T>
{
public:
singly_linked_list() : m_head(nullptr), m_size(0){}
~singly_linked_list() {erase_all();}
virtual int push_front(T t_value) override;
virtual T top_front() override;
virtual T pop_front() override;
virtual int push_back(T t_value) override;
virtual T top_back() override;
virtual T pop_back() override;
virtual bool find(T t_value) override;
virtual int erase(T t_value) override;
virtual void erase_all() override;
virtual bool empty() override;
virtual size_t size() override;
template<typename U>
friend node<U>* get_head(singly_linked_list<U>& t_list);
private:
node<T>* get_last_node();
node<T>* get_node_until(size_t t_index);
node<T>* find_node(T t_value);
node<T>* get_node_pointer(size_t t_position);
int find_node_index(T t_value);
singly_linked_list<T> get_all_addresses();
node<T>* m_head = nullptr;
size_t m_size;
};
/* O(1) */
template<typename T>
inline int singly_linked_list<T>::push_front(T t_value)
{
node<T>* new_node = new node<T>(t_value);
new_node->m_next = m_head;
m_head = new_node;
m_size++;
return 0;
}
/* O(1) */
template<typename T>
inline T singly_linked_list<T>::top_front()
{
if (empty())
{
std::cout << " list is empty " << std::endl;
return T();
}
return m_head->m_data;
}
/* O(1) */
template<typename T>
inline T singly_linked_list<T>::pop_front()
{
if (empty())
{
std::cout << " list is empty " << std::endl;
return T();
}
/* Value to be returned */
T value = m_head->m_data;
node<T>* next_node = m_head->m_next;
delete(m_head);
m_head = next_node;
m_size--;
return value;
}
/* O(N) */
template<typename T>
inline int singly_linked_list<T>::push_back(T t_value)
{
node<T>* new_node = new node<T>(t_value);
if (empty())
{
m_head = new_node;
m_size++;
return 0;
}
get_last_node()->m_next = new_node;
m_size++;
return 0;
}
/* O(N) */
template<typename T>
inline T singly_linked_list<T>::top_back()
{
if (empty())
{
std::cout << " list is empty " << std::endl;
return T();
}
return get_last_node()->m_data;
}
/* O(N) */
template<typename T>
inline T singly_linked_list<T>::pop_back()
{
T value;
if (empty())
{
std::cout << " list is empty " << std::endl;
return T();
}
if (size() == 1)
{
value = m_head->m_data;
delete(m_head);
m_head = nullptr;
m_size = 0;
return value;
}
node<T>* last_node = get_last_node();
node<T>* last_node_before = get_node_until(size() -1);
value = last_node->m_data;
delete(last_node);
last_node_before->m_next = nullptr;
m_size--;
return value;
}
/* O(N) - Worst case */
template<typename T>
inline bool singly_linked_list<T>::find(T t_value)
{
return find_node(t_value) != nullptr;
}
/* O(N) - Worst case */
template<typename T>
inline int singly_linked_list<T>::erase(T t_value)
{
/* Node with t_value deos not exists */
if (empty())
return -1;
if (size() == 1)
{
delete(m_head);
m_head = nullptr;
m_size = 0;
return 0;
}
int index = find_node_index(t_value);
if (index == -1)
return index;
node<T>* node_to_erase = get_node_until(index + 1);
node<T>* before_node_to_erase = get_node_until(index);
node<T>* after_node_to_erase = get_node_until(index + 2);
before_node_to_erase->m_next = after_node_to_erase;
delete(node_to_erase);
m_size--;
return 0;
}
/* O(N) - Worst case */
template<typename T>
inline void singly_linked_list<T>::erase_all()
{
while(m_head != nullptr)
{
node<T>* next_node = m_head->m_next;
delete(m_head);
m_size--;
m_head = next_node;
}
}
/* O(1) */
template<typename T>
inline bool singly_linked_list<T>::empty()
{
return (m_head == nullptr);
}
/* O(1) */
template<typename T>
inline size_t singly_linked_list<T>::size()
{
return m_size;
}
template<typename T>
inline node<T>* singly_linked_list<T>::get_last_node()
{
node<T>* start_node = m_head;
node<T>* last_node = nullptr;
/* Traverse until the end */
while (start_node != nullptr)
{
last_node = start_node;
start_node = start_node->m_next;
}
return last_node;
}
template<typename T>
inline node<T>* singly_linked_list<T>::get_node_until(size_t t_index)
{
node<T>* start_node = m_head;
node<T>* until_node = nullptr;
/* Traverse until the a node before last node */
size_t index(1);
while (start_node != nullptr)
{
until_node = start_node;
if (index == t_index)
{
return until_node;
}
start_node = start_node->m_next;
index++;
}
return nullptr;
}
template<typename T>
inline node<T>* singly_linked_list<T>::find_node(T t_value)
{
node<T>* start_node = m_head;
/* Traverse until the end */
while (start_node != nullptr)
{
if (t_value == start_node->m_data)
return start_node;
start_node = start_node->m_next;
}
return nullptr;
}
template<typename T>
inline int singly_linked_list<T>::find_node_index(T t_value)
{
node<T>* start_node = m_head;
/* Traverse until the end */
int index(0);
while (start_node != nullptr)
{
if (t_value == start_node->m_data)
return index;
start_node = start_node->m_next;
index++;
}
/* t_value not found*/
return -1;
}
/* Returns the address of the specified node position
form the linke list chain */
template<typename T>
node<T>* singly_linked_list<T>::get_node_pointer(size_t t_position)
{
auto start_node{m_head};
/* Traverse until the end */
size_t i(0);
while (start_node != nullptr)
{
if(i == t_position)
return start_node;
start_node = start_node->m_next;
i++;
}
return nullptr;
}
template<typename U>
node<U>* get_head(singly_linked_list<U>& t_list)
{
return t_list.m_head;
}
}
struct1 and struct2 have different size in bytes, so sizeof(struct1) != sizeof(struct2). Returning the struct from function requires copying it, so c++ requires you to specify the correct type for it so that correct amount of bytes can be copied. To start correct this problem you need to think in the very low level:
struct GenericStruct {
void *ptr;
size_t size;
type_info t;
};
struct1 extract_struct1(GenericStruct &s);
struct2 extract_struct2(GenericStruct &s)
{
if (s.size != sizeof(struct2)) throw -1;
if (s.t != typeid(struct2)) throw -1;
struct2 *s2 = (struct2*)s.ptr;
return *s2;
}
GenericStruct make_generic(const struct1 &ss)
{
GenericStruct s;
s.ptr = (void*)&ss;
s.size = sizeof(struct1);
s.t = typeid(struct1);
return s;
}
GenericStruct make_generic(const struct2 &ss);
the real problem is that these functions can fail on runtime, if the sizes or types do not match. The copying is obviously also needed:
GenericStruct Copy(const GenericStruct &s);
After these basic primitives exists, you can create a class which has copy constructor and assignment operator which uses these functions to implement proper generic struct support.