C++ declaring multiple classes in one header - c++

I got an assignment where I am supposed to create a Linked list by using CRTP. I got some starting code/suggestion on how to define the classes in their respective header files. I have omitted some code below:
Link.h
#include <iosfwd>
template<class T>
class List;
template<class T>
class Link {
Link* next;
friend class List<T>;
public:
Link();
virtual ~Link() = default;
//etc...
List.h
#include "Link.h"
template<class T>
class List : public Link<T> {
public:
List();
T* First();
T* Last();
//Etc...
This code compiles without any errors. Now my question is about the two first lines in Link.h, template<class T> class List;. I experimented a little bit and realized that Link.h won't compile without that class definition beacuse of the friend class List<T> statement. But why can't I just write #include "List.h" and remove the inheritance inside List.h and just use that definition from the start? I have tried this of course and get the error
"error: 'List' is not a class template
friend class List<T>;"
it would look like this:
Link.h
#include <iosfwd>
#include "List.h"
template<class T>
class Link {
Link* next;
friend class List<T>;
public:
Link();
virtual ~Link() = default;
List.h
#include "Link.h"
template<class T>
class List {
public:
List();
T* First();

Try to use a unique template in one file only or in files that build upon each other sequentially, not equally. In your case, you should probably move all of your files to one. Your .h files seem to mirror each other, so your compiler would have go back and forth between your references, but they do so in order. Choose the order of precedence.

Related

Friend class of template class problem (C++) (error: 'LinkedList' is not a class template)

I am trying to implement a generic Linked list in C++ and I get an error that I don't know how to deal with.
Here is my Link class implementation (which is also generic):
#ifndef LINK_H
#define LINK_H
#include <iostream>
#include "typeinfo.h"
#include "LinkedList.h"
template <class T>
class Link
{
public:
//|-------------------- Constructors --------------------
Link(T data): m_data(data), next(NULL){}
//|-------------------- Methods --------------------
T getData(){
return m_data;
}
T& getNext(){
return next;
}
void setNext(Link* newLink){
next = newLink;
}
void setData(T data){
m_data = data;
}
//|-------------------- Operator overload --------------------
bool operator==(Link& other){
if(this->m_data == other.m_data)
return true;
return false;
}
void operator++(){
this = this->next;
}
//|-------------------- Friend functions --------------------
friend std::ostream& operator<<(std::ostream& out,const Link<T>& link){
out<<link.m_data;
return out;
}
//|-------------------- Destructor --------------------
virtual ~Link(){}
protected:
private:
//|-------------------- Private fields --------------------
T m_data;
Link<T>* next;
friend class LinkedList<T>
};
#endif // LINK_H
As you can see I am trying to let LinkedList<T> be a friend of Link<T> so I can get access to
its fields (I want them to stay private).
Now, I think its relevant to post all of my LinkedList<T> implementation because its a lot of code, but here's how I defined the class:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include "List.h"
#include "Link.h"
template <class T>
class LinkedList : public List<T>
{
public:
and here are the fields:
private:
//|-------------------- Private fields --------------------
Link<T>* head;
Now, I get this error:
error: 'LinkedList' is not a class template
I have tried to search the error and found this.
But it does not seem to be the problem in my implementation.
I also found this.
But I could not understand how to implement this forward declaration in my case (or why I even need it).
I'd really appreciate clarification here.
Thanks in advance
Simply add a forward declaration of LinkedList before the definition of the Link class like this:
template<typename U>
class LinkedList;
// Now the definition as you have it above...
template <class T>
class Link
{
public:
...
See here.
BTW, you're missing a ; after your friend declaration in your first code block.

Defining a Nested Class From Header File

Still fairly new with C++ and trying to kick it up a notch here. I would like to build a Heap class, with a nested Node class, and add a heap sort aspect to the Heap class. I have done something similar with Java, but I am getting stuck trying to define the nested class in the .cpp file.
#pragma once
#ifndef HEAP_H
#define HEAP_H
template <class T>
class Heap
{
public:
class Node
{
public:
Node(T);
T data;
private:
Node *parent;
Node *left_child;
Node *right_child;
boolean is_root;
};
Heap(T*, int);
sort_it();
private:
T *unsorted_list
Node root;
void build_heap();
void add_node(Node);
void swap_root();
void trickle_down();
void heap_sort();
};
#endif
Now when I go to define my nested class in the .cpp file I cannot simply...
#include "stdafx.h"
#include "Heap.h"
#include <iostream>
//Defining Heap Constructor
Heap::Heap(T* incoming_array, int _size)
{
unsorted_list = incoming_array;
size = _size;
}
//Defining Node Constructor
Heap::Node(T _data)
{
data = _data;
left_child = right_child = parent = Null;
is_root = false;
}
I am not sure if my problem is how I am incorporating the template, or if my syntax for defining the inner class is wrong. Both Generic Programming and Nested Classes are unfamiliar to me in C++
If you use any generic type in nested class you have to specify the template.
template<class T>
class Node
To define the template class constructor outside the class,
template<typename T>
Node<T>::Node(T _data)
Declare the member as follows,
Node<T> root

Sorted Linked List in C++

Here is my problem.
I have a Linked List class as follows:
#include <iostream>
#include "List.h"
template <class Elem>
class LList : public List<Elem> { //List is a virtual base class
protected:
Node <Elem> *head;
Node <Elem> *fence;
Node <Elem> *tail;
int leftCount;
int rightCount;
void init();
void removeAll();
public:
LList();
~LList();
//Rest of methods overridden from List class
//////
};
Then I have a class called SortedLList which inherits from LList as follows:
#include "LinkedList.h"
#include "Helper.h"
template <class Elem>
class SortedLList : public LList<Elem> {
protected:
Helper *helper;
public:
SortedLList();
~SortedLList();
bool insert(const Elem&); //Override insertion method from LList class
};
In the implementation of SortedLList (SortledLList.cpp):
#include "SortedLList.h"
template <class Elem>
SortedLList<Elem>::~SortedLList() {
removeAll();
}
template <class Elem>
bool SortedLList<Elem>::insert(const Elem &_e) {
fence = head;
//Rest of Code..
}
I am having a compiler error that says : Use of undeclared identifier removeAll(). Same thing for fence and head pointers are not being recognized. What did I do wrong?
Thank You.
Because your class is a template there are certain issues that can happen to confuse the compiler. You may think your code is straight forward and easy to understand, and in this case it is. Older compilers used to do their best to guess and compile this code.
However, newer compilers are more strict and fail on all versions of this type of code, in order to prevent programmers from relying on it.
What you need to do is use the this pointer when calling base class functions. That makes the call unambiguous and clear. That would look like this->removeAll().
Another option would be to use a full name qualification like LList<Elem>::removeAll(). I prefer using this because it is easier to read.

Template class compilation "expected constructor, destructor, or type conversion before ‘<’ token" error

I'm having trouble with compiling my template class. This is my list.cpp
using namespace std;
template <class T>
List<T>::List()
{
length = 0;
}
template <class T>
List<T>::~List()
{
}
template <class T>
List<T> & List<T>::operator=(const List<T> & rhs)
{
List<T> hha;
return hha;
}
template <class T>
int List<T>::size()
{
return length;
}
ANd this is my list.h
#ifndef _LIST_H_
#define _LIST_H_
#include <iterator>
#include <ostream>
using namespace std;
template <class T>
class List
{
private:
class ListNode
{
public:
ListNode();
ListNode(const T element);
ListNode *next;
T data;
};
public:
// big3
List();
~List();
List<T> & operator=(const List<T> & rhs);
int size();
bool empty();
void print(ostream & os) const;
private:
ListNode * head;
ListNode * tail;
int length;
};
#include "list.cpp"
#endif
when I run g++ list.cpp
I get errors
expected constructor, destructor, or type conversion before ‘<’ token
for definitions of constructor, destructor, and operator...
I don't know what seems to be wrong
The template implementation goes in the header.
It is a bit of a hack but it is how it is done.
The problem you currently encounter is that you list.cpp doesn't include you list.h: the compiler sees a couple of definitions for things which aren't declared, yet. You can fix this problem by including list.h at the top of your file:
#include "list.h"
...
However, this will essentially lead to a problem coming: if you actually want to use your List<T> with some type, the compiler will need to see the template definition where the class template is used. That is, typically you will implement your templates in the header file. The alterntaive is to implement templates in an implementation file and explicitly instantiating the types it is to be used with. This is quite reasonable for some templates but for something intended to be used for an unknown number of types this isn't practical.
BTW, you are using names which you are not allowed to touch: names starting with an underscore followed by a capital letter are reserved for the C++ implementation, i.e. the compiler and the standard library. Names using two consecutive underscores anywhere are also reserved.
Since list.hpp doesn't get #included in list.cpp, the compiler doesn't know about the template definition in that header when you try to compile list.cpp.
You compile list.cpp, that defines your list member functions. But it doesn't contain the template class declaration - that is in the header.
I see you include cpp in your list header. This will sort of work if you include the list header in some other cpp file and make sure list.cpp will not be compiled as a separate compilation unit.
What I mean is i.e. file main.cpp:
#include "list.h"
int main()
{}
Then compile this with g++ main.cpp.
Usually you just want to avoid cpp files when using templates altogether. Just stuff everything in the header and include that. Or alternatively I would at least rename your list.cpp to list.impl or some other name. This way one might be less tempted to actually try to compile that file directly.

c++ templates and inheritance

I'm experiencing some problems with breaking my code to reusable parts using templates and inheritance. I'd like to achieve that my tree class and avltree class use the same node class and that avltree class inherits some methods from the tree class and adds some specific ones. So I came up with the code below. Compiler throws an error in tree.h as marked below and I don't really know how to overcome this. Any help appreciated! :)
node.h:
#ifndef NODE_H
#define NODE_H
#include "tree.h"
template <class T>
class node
{
T data;
...
node()
...
friend class tree<T>;
};
#endif
tree.h
#ifndef DREVO_H
#define DREVO_H
#include "node.h"
template <class T>
class tree
{
public: //signatures
tree();
...
void insert(const T&);
private:
node<T> *root; //missing type specifier - int assumed. Note: C++ does not support default-int
};
//implementations
#endif
avl.h
#ifndef AVL_H
#define AVL_H
#include "tree.h"
#include "node.h"
template <class T>
class avl: public tree<T>
{
public: //specific
int findMin() const;
...
protected:
void rotateLeft(node<T> *)const;
private:
node<T> *root;
};
#endif
avl.cpp (I tried separating headers from implementation, it worked before I started to combine avl code with tree code)
#include "drevo"
#include "avl.h"
#include "vozlisce.h"
template class avl<int>; //I know that only avl with int can be used like this, but currently this is doesn't matter :)
//implementations
...
Both tree.h and node.h try to include each other, the include guards will prevent one of them from seeing the other.
Instead of #include "tree.h" try forward declaring tree like:
template <class T>
class tree;
in node.h
EDIT: As sbi suggested in a comment, it makes more sense to forward declare tree in node.h than the other way around, since it's about granting tree access to node through a friend declaration.
Don't #include "tree.h" in "node.h".
Also, you've declared root in both the tree and avl classes. Qualify tree::root as protected and remove avl::root.
Your problem is that tree.h includes node.h and vice versa. I would not have thought it is necessary (or makes much sense) for the node to have to know about the tree or to grant it friendship, so I'd remove that.
The problem is because of the circular dependency of header files between tree.h and node.h . Since node.h includes tree.h, while compiling the tree class, compiler doesn't know what is the type of node. Since you are using it just for declaring a friend there is no need to include the header file tree.h in node.h