I wrote this something-like-stack data structure:
template<class T>
class Stos {
class Element {
public:
T n;
Element* prev;
Element(const T& k = 0): n(k), prev(0) {}
};
Element* member;
Stos(Stos&);
public:
Stos(const T&);
~Stos();
unsigned int count;
T get();
Element* push(const T&);
T pop();
void mod(const T&);
};
And implementation (same file):
template<class T>
Stos<T>::Stos(const T& n = 0): count(1) {
member = new Element(n);
}
template<class T>
T Stos<T>::get() {
return member->n;
}
template<class T>
Stos<T>::Element* Stos<T>::push(const T& n = 0) {
Element* point = member;
member = new Element;
member->prev = point;
if(n != 0) member->n = n;
++count;
return member;
}
template<class T>
T Stos<T>::pop() {
Element* point = member;
T n = point->n;
member = point->prev;
--count;
delete point;
return n;
}
template<class T>
void Stos<T>::mod(const T& n) {
member->n = n;
}
template<class T>
Stos<T>::~Stos() {
while(member) pop();
}
And when I try to compile it with g++, I get this error about the first line of definition of Stos::Element* Stos::push(): expected constructor, destructor, or type conversion before ‘*’ token. It is my first try to write something with templates. This stack code did work without templates, when I'd edited it, then I got the error, everything worked just fine before with "int" everywhere instead of "T".
And I can't find out why it doesn't compile. Can't I use pointer to class::member?
You need to prefix the name Element with typename
typename Stos<T>::Element* Stos<T>::push(const T& n = 0)
Here's a link to a full explanation of why this is necessary
http://pages.cs.wisc.edu/~driscoll/typename.html
You should also consider using
const T &n = T()
instead of
const T &n = 0
Since not all possible T may be able to be initialized from 0!
Related
I have a linked list that contains a pointer to the first and last node and size which indicates how many nodes are there in the list.
I have a function that returns the first node.
I want to be able to change the m_data in the first node using queue1.front() = 3;. However, I am getting
invalid conversion from ‘int’ to ‘Node<int>*’
error while compiling
template <class T>
class Node {
public:
Node(const T& t);
~Node() = default; // Destructor
Node(const Node&) = default; // Copy Constructor set to default
Node& operator=(const Node&) =
default; // Assignment operator set to default
T& getData();
const T& getData() const;
Node* getNext();
void setNext(Node<T>* newNext);
private:
T m_data;
Node* m_nextNode;
};
template <class T>
Node<T>::Node(const T& t) {
this->m_data = t;
this->m_nextNode = nullptr;
}
template <class T>
class Queue {
public:
static const int SIZE_EMPTY = 0;
Queue();
~Queue(); // Destructor
Queue(const Queue&) = default; // Copy Constructor set to default
Queue& operator=(const Queue&) =
default; // Assignment operator set to default
void pushBack(const T& t);
Node<T>*& front();
const Node<T>*& front() const;
void popFront();
int size() const;
class EmptyQueue {};
private:
Node<T>* m_head;
Node<T>* m_tail;
int m_size;
};
template <class T>
Node<T>*& Queue<T>::front() {
if (this->m_size == Queue<T>::SIZE_EMPTY) {
throw Queue<T>::EmptyQueue();
}
return this->m_head;
}
template <class T>
void Queue<T>::pushBack(const T& t) {
this->m_size += 1;
Node<T>* newNode = new Node<T>(t);
this->m_tail = newNode;
if (this->m_size == 1) {
this->m_head = newNode;
} else {
Node<T>* tempNode = this->m_head;
while (tempNode->getNext()) {
tempNode = tempNode->getNext();
}
tempNode->setNext(newNode);
}
}
int main() {
Queue<int> queue1;
queue1.pushBack(1);
queue1.front() = 3;
}
Queue<T>::front() is returning a Node<T>*& when it should return a T&.
Example:
template <class T>
T& Queue<T>::front() {
if (this->m_size == Queue<T>::SIZE_EMPTY) {
throw Queue<T>::EmptyQueue();
}
return m_head->getData();
}
template <class T>
const T& Queue<T>::front() const {
if (this->m_size == Queue<T>::SIZE_EMPTY) {
throw Queue<T>::EmptyQueue();
}
return m_head->getData();
}
You also need to make the same change in the class definition:
template <class T>
class Queue {
public:
//...
T& front();
const T& front() const;
//...
};
The problem is that Queue<T>::front returns a Node<T>* by reference and so by writing queue1.front() = 3; you're trying to assign an int to an Node<int>*.
queue1.front() = 3;
In the above statement, the left hand side result has a type Node<int>* but the right hand side is 3 which is an int. Thus the type on the left hand side and right hand side mismatch and since there is no implicit conversion from an int to a Node<int>*, you get the mentioned error:
invalid conversion from ‘int’ to ‘Node<int>*
I have a class like this:
#include <iostream>
template <class T>
class LL
{
using size_t = unsigned int;
class Node
{
T m_data;
Node* m_next;
Node(const T& data) :m_data{ data }, m_next{ nullptr }{}
friend std::ostream& operator<<(std::ostream& out, const Node& node)
{
out << node.m_data;
return out;
}
friend std::ostream& operator<<(std::ostream& out, const LL& ll);
friend class LL;
};
Node* m_first{ nullptr };
size_t m_size{ 0 };
Node* newNode(const T& data)
{
return new Node{ data };
}
public:
void push(const T& data)
{
Node* temp = newNode(data);
temp->m_next = m_first;
m_first = temp;
++m_size;
}
Node* head()
{
return m_first;
}
size_t size() const
{
return m_size;
}
~LL()
{
if (m_first)
{
Node* trav = m_first->m_next;
Node* foll = m_first;
while (trav)
{
delete foll;
foll = trav;
trav = trav->m_next;
}
delete foll;
}
}
friend std::ostream& operator<<(std::ostream& out, const LL& ll)
{
Node* trav = ll.m_first;
while (trav)
{
out << *trav << ' ';
trav = trav->m_next;
}
return out;
}
};
I also have a function template somewhere else below this class in the same file that tries to access Node and looks like this with two compiler errors:
template <typename T>
int getSize(LL<T>::Node* node) //C2065: node is undeclared, C3861: node is not found
{
if (node)
{
return 1 + getSize(node->m_next);
}
return 0;
} //does not compile
After sometime I tried this, again with two compiler:
template <typename T>
int getSize(LL<T>::Node<T>* node) //C2065 like before, C7510: use of dependent template name must be prefixed with 'template'
{
if (node)
{
return 1 + getSize(node->m_next);
}
return 0;
} //does not compile
After sometime again, I tried the below which compiled fine.
template <typename T>
int getSize(typename LL<T>::template Node<T>* node)
{
if (node)
{
return 1 + getSize(node->m_next);
}
return 0;
}
Now, when I tried to call this function from my driver function, I got compiler errors again:
int main()
{
LL<int> ll;
std::cout << getSize(ll.head()); //E0304, C2672 and C2783
//E0304: no instance of the function template "getSize" matches the argument list
//C2672: no matching overload function found
//C2783: could not deduce template argument for 'T'
}
I tried everything that I possible could and couldn't sort this problem out. Could someone please explain me what is going on?
Note: All codes that I've mentioned here are in the same file.
getSize(ll.head()) fails because of non-deduced context; template parameter T can't be deduced automatically.
If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.
1) The nested-name-specifier (everything to the left of the scope resolution operator ::) of a type that was specified using a qualified-id:
The declaration should be
template <typename T>
int getSize(typename LL<T>::Node* node) // using class instead of typename works for OP (MSVC)
{
//some code
}
And since Node is not a template you don't need to use template keyword.
LIVE
See Where and why do I have to put the “template” and “typename” keywords? about why use the keyword typename and template.
This is a General Trees program, where I am trying to find the depth of the tree (depth of 2) and calculate the size of the directory. The two errors are declaration errors (towards the bottom of Tree.cpp) and can't seem to declare the function properly.
Tree.cpp
#include "Tree.h"
#include <iostream>
using namespace std;
template <typename E>
bool Tree<E>::Position::isRoot() const
{
if (u->parent == NULL)
return true;
else
return false;
}
template <typename E>
bool Tree<E>::Position::isExternal() const
{
return (u->child.empty());
}
template <typename E>
bool Tree<E>::Position::operator==(Tree<E>::Position p)
{
if (u == p.u)
return true;
else
return false;
}
template <typename E>
Tree<E>::Position::Position(TreeNode *v)
{
u = v;
}
template <typename E>
typename Tree<E>::Position Tree<E>::Position::parent()
{
return Tree<E>::Position(u->parent);
}
template <typename E>
typename Tree<E>::PositionList Tree<E>::Position::children()
{
return (u->child);
}
template <typename E>
E Tree<E>::Position::operator*()
{
return u->e;
}
template <typename E>
typename Tree<E>::Position Tree<E>::root()
{
return typename Tree<E>::Position(r);
}
template <typename E>
int Tree<E>::size() const
{
return this->n;
}
template <typename E>
bool Tree<E>::empty() const
{
return size() == 0;
}
template <typename E>
void Tree<E>::insert(E e, Tree<E>::Position p)
{
TreeNode *v = new TreeNode() ;
v->e = e;
if (empty())
v->parent = NULL;
else
v->parent = p.u;
if (!empty() )
{
p.u->child.insertBack(v);
}
else
{
v->parent = NULL;
r = v;
}
++n;
}
template <typename E>
NodeList<typename Tree<E>::Position> Tree<E>::Positions()
{
typename Tree<E>::PositionList list;
preorder(r, list);
return list;
}
template <typename E>
void Tree<E>::preorder(Tree<E>::Position p, Tree<E>::PositionList &pl)
{
pl.insertBack(p);
if (p.u->child.empty()==false)
for(typename Tree<E>::PositionList::Iterator ii = p.u->child.begin(); ii!= p.u->child.end(); ++ii)
preorder(*ii, pl);
}
template <typename E>
int Tree<E>::depth(Tree<E>::TreeNode& u, Tree<E>::Position& p) //ERROR: Out-of-line definition of 'depth' does not match any declaration in 'Tree<E>'
{
if (p.isRoot())
return 0;
else
return 1+depth(u, p.parent());
}
template <typename E>
int Tree<E>::directorySize(Tree<E>::TreeNode& u, Tree<E>::Position& p) //Out-of-line definition of 'directorySize' does not match any declaration in 'Tree<E>'
{
int s = size(p);
if (!p.isExternal())
{
PositionList ch = p.children();
for (typename Tree<E>::PositionList::Iterator q = ch.begin(); q != ch.end(); q++)
s += depth(u, *q);
cout << name(p) << ": " << s << endl;
}
return s;
}
Tree.h
#ifndef TREE_H
#define TREE_H
#include <cstdlib>
#include "NodeList.cpp"
template <typename E>
class Tree {
public:
class TreeNode;
public:
class Position // a node position
{
public:
E operator*(); // get element
Position parent();
NodeList<Position> children();
bool isRoot() const; // root node?
bool isExternal() const; // external node?
bool operator==(Position p);
int depth(const Tree& u, const Position& p); //DECLARED(ERROR) - DEPTH OF TWO FUNCTION
Position(typename Tree<E>::TreeNode *v);
Position(){}
typename Tree<E>::TreeNode *u;
friend class NodeList<Position>;
};
typedef NodeList<typename Tree<E>::Position> PositionList;
public:
class TreeNode
{
E e;
TreeNode *parent;
typename Tree<E>::PositionList child;
friend class Tree;
friend class Tree<E>::Position;
public:
TreeNode(){
parent = NULL;
}
TreeNode(E,Tree<E>::Position*, Tree<E>::PositionList*);
TreeNode& operator=(const TreeNode &t)
{
parent = t.parent;
child = t.child;
e = t.e;
}
};
public: // public functions of Tree
Tree<E>(){
n = 0;
}
int size() const; // number of nodes
bool empty() const; // is tree empty?
int directorySize(const TreeNode& u, const Position& p); //DECLARED(ERROR) - SIZE OF DIRECTORY
Position root();
PositionList Positions();
void insert(E e, Position p);
void preorder(Position p ,PositionList &pre_order);
private:
TreeNode *r;
int n;
friend class Position;
};
#endif
The error is only showing up in the Tree.cpp file.
There are multiple errors here:
The arguments are declared to be const qualified references but the const got dropped in the definitions.
depth() is a member of Tree<E>::Position not of Tree<E>.
The first parameter of depth() is a Tree<E> not a TreeNode.
Note that putting the code into a .cpp file is either confusion (if the intention is to include the file) or it will cause grief when using the template classes from another translation unit. This problem is unrelated to the question, though.
I am using Microsoft Visual Studios and I have create a generic class List_Array. There is no problem with the default constructor, but the other two (overloaded) constructors are generating the error.
//List_Array.h
template<typename T>
class List_Array {
private:
int size; ...
T* data;
public:
List_Array<T>::List_Array();
List_Array<T>::List_Array(int);
List_Array<T>::List_Array(const T&, int);
...
};
template<typename T>
List_Array<T>::List_Array() { }
template<typename T>
List_Array<T>::List_Array(int s) {
this->size = s
this->data = new T[s];
}
template<typename T>
List_Array<T>::List_Array(const T& init, int s){
this->size = s;
this->data = new T[s];
for (int i = 0; i < s; i++){
this->data[i] = init;
}
}
I get a C2244 'List_Array::List_Array': unable to match function definition to an existing declaration
Any help is much appreciated!
The problem has nothing to do with template or overloading. You just don't need List_Array<T>:: part for the member function declaration inside class definition. i.e.
template<typename T>
class List_Array {
private:
int size; ...
T* data;
public:
List_Array();
List_Array(int);
List_Array(const T&, int);
...
};
LIVE
I have implemented a stack using the next class:
template <typename T, int lungime> class Depou
{
private:
T *depouarray;
int top;
public:
Depou ()
{
this -> top = -1;
depouarray = (T *) calloc (lungime, sizeof (T));
}
~Depou ()
{
free (depouarray);
}
void push (T x)
{
if (top >= lungime - 1)
{
return;
}
top ++;
depouarray [top] = x;
}
T pop ()
{
if (isEmpty ())
{
return -1;
}
T x;
x = depouarray [top];
top --;
return x;
}
T peek ()
{
if (isEmpty ())
{
return -1;
}
return depouarray[top];
}
int isEmpty ()
{
return (top < 0);
}
}
My problem is the next one:
After I've added an element to the stack, let's say 3, I verified it and it showed 3.
Next, I added another element, let's say 4, I verified the content of the stack and it showed a very high number (which is surely junk) and 4. I cannot understand why it transforms the first elements into junk, leaving only the last element added as it should be.
As my colleague pointed out, you have many errors within your code and I think i t would be too much effort to correct it. Hence I'm giving you a stack implementation.
A stack is a FILO structure. The best way to implement it is to use Node and to link them together. Look at the code below, it is straight forward. Let me know if you have questions.
template <class T>
class Stack {
public:
Stack();
~Stack();
void push(const T&);
void pop(T& out);
T pop();
bool is_empty() const;
void clear();
private:
class Node {
public:
Node(const T& t, Node* c);
T contain;
Node* next;
};
Node* peak;
};
template <class T>
Stack<T>::Stack()
{
peak = NULL;
}
template <class T>
Stack<T>::~Stack()
{
clear();
}
template <class T>
bool Stack<T>::is_empty() const
{
return peak == NULL;
}
template <class T>
void Stack<T>::clear()
{
while(!is_empty())
pop();
}
template <class T>
Stack<T>::Node::Node(const T& t, Node* c) : next(c)
{
contain = t;
}
template <class T>
void Stack<T>::push(const T& t)
{
peak = new Node(t, peak);
assert(peak);
}
template <class T>
T Stack<T>::pop()
{
assert(peak);
Node c(*peak);
delete peak;
peak = c.next;
return c.contain;
}
template <class T>
void Stack<T>::pop(T& t)
{
assert(peak != NULL);
t = peak->contain;
Node* c = peak;
peak = peak->next;
delete c;
}