how to remove error : X is not a class template - templates

I'm no expert in using templates but I'm not sure why I'm getting error: 'SLinked_List' is not a class template: friend class SLinked_List<T>; in the definition of class SNode. What is wrong with this piece of code?
Thank you,
Pranav
#include <iostream>
#include <string>
template <typename T>
class SNode{
friend class SLinked_List<T>;
private:
T data;
SNode<T>* next;
};
template <typename T>
class SLinked_List{
private:
SNode<T>* head;
public:
SLinked_List(){
head = nullptr;
}
bool empty() const { return head == nullptr; }
void insert_first (const T&);
};
template <typename T>
void SLinked_List<T> :: insert_first (const T& t){
SNode<T>* node = new SNode<T>;
node->data = t;
node->next = head;
head = node;
}
int main(){
SLinked_List<std::string> ls;
ls.insert_first("Hello");
return 0;
}

When you use template arguments to refer to a name you are saying that this type already exists as a template and I want to reference a specific specialization of that template. Inside SNode, SLinked_List hasn't been declared yet, so this can't be allowed because the compiler doesn't even know if it's a template yet.
It's clear you want to befriend the specialization taking a T, so you need to declare SLinked_List before SNode:
template <typename T>
class SLinked_List;
template <typename T>
class SNode{
friend class SLinked_List<T>;
private:
T data;
SNode<T>* next;
};
Now the compiler knows that SLinked_List is a template and can be referenced as such.

Related

template class header file

I'm trying to implement stack data structure using singly linked list.
This is the header file that has template class of Node and List
#pragma once
template <typename E>
class SNode {
E elem;
SNode<E>* next;
public:
friend class SLinkedList<E>;
};
template <typename E>
class SLinkedList {
private:
SNode<E>* head;
public:
SLinkedList();
~SLinkedList();
bool empty() const ();
const E& front() const;
void addFront(const E& e);
void removeFront();
};
template <typename E>
SLinkedList<E>::SLinkedList() : head(NULL) {}
template <typename E>
SLinkedList<E>::~SLinkedList() {
while(!empty()) removeFront();
}
template <typename E>
bool SLinkedList<E>::empty() const {
return head==NULL;
}
template <typename E>
const E& SLinkedList<E>::front() const {
return head->elem;
}
template <typename E>
void SLinkedList<E>::addFront(const E& e) {
SNode<E>* tmp = new SNode<E>;
tmp->elem = e;
tmp->next=head;
head=tmp;
}
template <typename E>
void SLinkedList<E>::removeFront() {
SNode<E>* old = head;
head=head->next;
delete old;
}
This is a simple main code
#include <iostream>
#include "SNode.h"
using namespace std;
int main() {
SNode<int> A(1);
SNode<int> B(2);
SLinkedList<int> L();
L.push(A);
L.push(B);
return 0;
}
When I compile this code the compiler says
SLinkedList is not a class template
I have no idea why it says that since I did put
template
You need to forward declare the SLinkedList templated class. like this:-
template <typename E>
class SLinkedList;
template <typename E>
class SNode {
E elem;
SNode<E>* next;
public:
friend class SLinkedList<E>;
};
...
There are other errors in you code. I hope you are able to resolve them by youself.
You have vexing parse with
SLinkedList<int> L();
Which declares a.. function L, taking no parameters, and returning SLinkedList<int>.
Use
SLinkedList<int> L;
or
SLinkedList<int> L{};

Errors with friend function in Clion c++

I have written a small code to practice data structures and the beautiful C++.
The code below works completely fine if make the variables in SNode to public and remove the friend class ... line. However, based on the textbook I'm reading, this should be working fine.
The errors I get are as follow:
line 11: error: ‘SLinkedList’ is not a class template
In instantiation of ‘class SNode’: line 10: error: template argument required for ‘class SLinkedList’
In instantiation of ‘void SLinkedList::addFront(const E&) [with E = int]’: line 9: error: ‘int SNode<int>::elem’ is private
Below is the code written in Clion:
#include <iostream>
using namespace std;
template <typename E>
class SNode {
private:
E elem; //line 9
SNode<E> * next; // line 10
friend class SLinkedList<E>; //Provide SLinkedList access to these private variables (line 11)
};
template <typename E>
class SLinkedList {
public:
SLinkedList();
~SLinkedList();
bool empty() const;
const E& front() const;
void addFront(const E& e);
void removeFront();
void printAll() const;
private:
SNode<E> * head;
};
template <typename E>
SLinkedList<E>::SLinkedList():head(NULL){};
template <typename E>
bool SLinkedList<E>::empty() const {
return (head==NULL);
}
template <typename E>
void SLinkedList<E>::addFront(const E &e) {
SNode<E> * node = new SNode<E>;
node->elem=e;
node->next=head;
head=node;
}
template <typename E>
void SLinkedList<E>::removeFront() {
SNode<E> * temp = head;
head = head->next;
delete temp;
}
template <typename E>
const E& SLinkedList<E>::front() const {
return head->elem;
}
template <typename E>
SLinkedList<E>::~SLinkedList() {
while (!empty()){
removeFront();
}
}
template <typename E>
void SLinkedList<E>::printAll() const {
SNode<E> * itr =head;
while (itr != NULL){
cout<<itr->elem<<" ";
itr = itr->next;
}
}
int main() {
cout << "Hello, World!" << endl;
SLinkedList<int> test ;
test.addFront(2);
test.addFront(3);
test.addFront(6);
test.addFront(8);
test.addFront(19);
test.printAll();
return 0;
}
friend class SLinkedList<E>;
This template is not declared yet. Your C++ code gets compiled in an orderly manner, from the beginning of your source file to the end. Until this template gets declared later on in this header file, the compiler has no clue what this is.
The solution is very simple: add a forward declaration to the beginning of the header file, because the SNode template declaration:
template <typename E> class SLinkedList;
template <typename E>
class SNode {
private:
E elem;
SNode<E> * next;
friend class SLinkedList<E>;
};
friend class SLinkedList<E>;
At this point SLinkedList is not defined yet as a template, hence giving the error. Give a forward declaration for SLinkedList, everything will be fine than.
Add this :-
template <typename E>
class SLinkedList;

Nested template class constructor

I the compiler can't find the definition of my constructor for the nested class.
My nested class Node is in the middle and the constructor is at the end.
Errors:
error C2244: 'CircularDoubleDirectedList::Node::Node' : unable
to match function definition to an existing declaration see
declaration of 'CircularDoubleDirectedList::Node::Node'
definition
'CircularDoubleDirectedList::Node::Node(const T &)'
existing declarations
'CircularDoubleDirectedList::Node::Node(const T &)'
Code:
#ifndef CIRCULARDOUBLEDIRECTEDLIST_H
#define CIRCULARDOUBLEDIRECTEDLIST_H
#include "ICircularDoubleDirectedList.h"
template <typename T> class CircularDoubleDirectedList;
template <typename T> class Node;
template <typename T>
class CircularDoubleDirectedList :
public ICircularDoubleDirectedList<T>{
public:
//Variabels
Node<T>* current;
int nrOfElements;
direction currentDirection;
//Functions
CircularDoubleDirectedList();
~CircularDoubleDirectedList();
void addAtCurrent(const T& element) override;
private:
template <typename T>
class Node
{
public:
T data;
Node<T>* forward;
Node<T>* backward;
Node(const T& element);// The constructor
};
};
template <typename T>
CircularDoubleDirectedList<T>::CircularDoubleDirectedList(){
this->nrOfElements = 0;
this->current = nullptr;
this->currentDirection = FORWARD;
}
template <typename T>
CircularDoubleDirectedList<T>::~CircularDoubleDirectedList(){
//TODO: Destroy all nodes
}
template <typename T>
void CircularDoubleDirectedList<T>::addAtCurrent(const T& element){
Node<T>* newNode = new Node<T>(element);
newNode->data = element;
if (this->nrOfElements == 0){
newNode->forward = newNode;
newNode->backward = newNode;
}
else{
//this->current->forward = newNode;
//this->current->forward->backward = newNode;
}
//this->current = newNode;
}
template <typename T>
CircularDoubleDirectedList<T>::Node<T>::Node(const T& element){
this->data = element;
}
#endif
First, the forward-declared template <typename T> class Node; is not the same as CircularDoubleDirectedList::Node - the former is a global class template, the latter is a nested class.
Second, you don't need to declare CircularDoubleDirectedList::Node as a template (and if you do, you have to use another template parameter name for it, not T). But as I understand, for this case you should just make it non-template, so:
template <typename T>
class CircularDoubleDirectedList :
public ICircularDoubleDirectedList<T>{
private:
class Node
{
public:
T data;
Node* forward;
Node* backward;
Node(const T& element);// The constructor
};
public:
Node* current;
//...
};
template <typename T>
CircularDoubleDirectedList<T>::Node::Node(const T& element){
this->data = element;
}
You have two class templates named Node, while in reality you want one non-template class named Node. You have forward-declared ::Node<T>, and you have the nested ::CircularDoubleDirectedList<T>::Node<U>.
If you really want it like that, you'll have to add another template keyword to the constructor definition:
template <typename T> //because CircularDoubleDirectedList is a template
template <typename U> //because Node is a template
CircularDoubleDirectedList<T>::Node<U>::Node(const T& element) : data(element)
{}
However, I can't see a single reason to have Node be a template. Inside CircularDoubleDirectedList<T>, do you want to use nodes with type other than T? If not, make Node a normal non-template class:
template <typename T>
class CircularDoubleDirectedList :
public ICircularDoubleDirectedList<T>{
public:
//Variabels
Node<T>* current;
int nrOfElements;
direction currentDirection;
//Functions
CircularDoubleDirectedList();
~CircularDoubleDirectedList();
void addAtCurrent(const T& element) override;
private:
class Node
{
public:
T data;
Node* forward;
Node* backward;
Node(const T& element);// The constructor
};
};
template <typename T>
CircularDoubleDirectedList<T>::Node::Node(const T& element) : data(element)
{}

Template class not inheriting the protected variable from another Template class

I'm making a Linked list which is generic in nature and have some basic functionality. Then I'm trying to make another template class called "Set" which is inheriting from LinkedList. But when I try to access "head" which is a Node<>* defined in Linked List. It's giving an error. My files are:
LinkedList.h
template <typename T>
struct Node {
T data;
Node<T> *next;
};
template <typename T>
class LinkedList {
public:
Node<T>* head;
int size;
LinkedList();
LinkedList(const LinkedList<T> &lst);
~LinkedList();
Node<T>* getHead();
Node<T>* getTail();
};
template <typename T>
class Set:public LinkedList<T> {
public:
void insert(T item);
friend ostream&(ostream& out, const Set<T> set)
};
and an implementation of insert is:
template <typename T>
void Set<T>::insert(T item) {
Node<T>* temp = head;
bool present = false;
while (temp != NULL) {
if (temp->data == item) {
present = true;
}
temp = temp->next;
}
if (present == false) {
/*Node<T> *tail = getTail();
Node<T>* newTail = new Node<T>(item);
newTail->next = NULL;
tail->next = newTail;*/
}
}
It says:
error: "head" was not declared in this scope in line "Node<T>* temp = head"
This C++ oddity is due to two-phase lookup and the fact that head is a dependant name (as a member of a base class that depends on the "current" class's template arguments):
[C++11: 14.6.2/3]: In the definition of a class or class template, if a base class depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member. [..]
Bypass unqualified lookup by introducing this into the expression (per [C++11: 3.4.5]):
Node<T>* temp = this->head;
// ^^^^^^
There's a longer explanation on this previous Stack Overflow answer:
Why do I have to access template base class members through the this pointer?
Here's a minimal(ish) testcase:
#include <iostream>
template <typename T>
struct Base
{
int x = 42;
};
template <typename T>
struct Derived : Base<T>
{
void foo();
};
template <typename T>
void Derived<T>::foo()
{
std::cout << x << '\n';
}
int main()
{
Derived<void> d;
d.foo();
}
// main.cpp: In member function 'void Derived<T>::foo()':
// main.cpp:18:18: error: 'x' was not declared in this scope
// std::cout << x << '\n';
// ^
(live demo)
To fix, change foo thus:
template <typename T>
void Derived<T>::foo()
{
std::cout << this->x << '\n';
}
(live demo)
You're inheriting from a dependent base class so member access needs to be qualified with this:
Node<T>* temp = this->head;
For more information, see this thread.

Template Class data type

I've created this pretty simple dynamic list which is implemented with a template class:
Node.h
template <class T> class Node
{
public:
typedef T data_type;
typedef T& reference_type;
void setData(data_type);
void setNextNull();
void setNext(Node*);
reference_type getData();
Node* getNext();
private:
data_type data;
Node* next;
};
template <class T> void Node<T>::setData(data_type _data)
{
data=_data;
}
template <class T> void Node<T>::setNextNull()
{
next=NULL;
}
template <class T> void Node<T>::setNext(Node* _next)
{
next=_next;
}
template <class T> typename Node<T>::reference_type Node<T>::getData()
{
return data;
}
template <class T> typename Node<T>::Node* Node<T>::getNext()
{
return next;
}
List.h
#ifndef LIST_H
#define LIST_H
#include <Node.h>
template <class T> class List
{
public:
typedef Node<T> node_type;
typedef node_type* node_pointer;
typedef T data_type;
typedef T& reference_type;
List();
void push_back(data_type);
reference_type at(int);
void clear();
void swap(int,int);
int size();
private:
int list_size = 0;
node_pointer head, tail;
};
template <class T> List<T>::List()
{
head=NULL;
}
template <class T> void List<T>::push_back(data_type data)
{
if(head == NULL) {
head = new node_type;
head->setData(data);
tail = head;
} else {
node_pointer temp = new node_type;
temp->setData(data);
temp->setNextNull();
tail->setNext(temp);
tail = tail->getNext();
}
list_size++;
}
template <class T> typename List<T>::reference_type List<T>::at(int x)
{
node_pointer pointer=head;
for(int i=0; i<x; i++)
pointer=pointer->getNext();
return pointer->getData();
}
template <class T> void List<T>::clear()
{
node_pointer pointer = head;
for(int i=0; i<list_size; i++) {
node_pointer temp = pointer;
pointer=pointer->getNext();
delete(temp);
}
head=NULL;
list_size=0;
}
template <class T> void List<T>::swap(int x, int y)
{
data_type buffer=at(x);
at(x)=at(y);
at(y)=buffer;
}
template <class T> int List<T>::size()
{
return list_size;
}
#endif // LIST_H
The list works perfectly with any form of data type, except when i use a class with a parameter inside it's constructor, then I get this error:
include/Node.h error: no matching function for call to ‘Player::Player()’
What am I doing wrong??
UPDATE 1
I've added a simple constructor as suggested but I get the same error
template <class T> Node<T>::Node(data_type _data)
{
data=_data;
}
You probably haven't defined a default constructor for your Player class. Just insert an empty constructor
Player() {}
And your problem will likely to be solved.
When you write a template method and use it in the main function like this:
Node<Player>
The compiler automatically calls the constructor of the Player class.
If you didn't define any constructors in Player, the compiler will use default constructor. However, any constructor you defined will hide the default one and force you to use this one.
For instance, a constructor like
Player(string, int, int)
Prevents you to create an object like this:
Player *p = new Player();
However, if you haven't written the constructor, the piece of code above would've worked just fine.
That's why your template needs a default constructor, iff you defined a parameterized constructor.
Your class Node should have a constructor which take a T so you can construct your T by copy instead of requiring to have a default constructor and copy.
your Node class would be something like:
template <class T>
class Node
{
public:
Node(const T& data) : data(data), next(0) {}
void setNextNull();
void setNext(Node*);
const T& getData() const { return data; }
T& getData() { return data; }
Node* getNext();
private:
T data;
Node* next;
};
and so you transform
head = new node_type;
head->setData(data);
by
head = new node_type(data);