sample code:
file: LinkedStack.h
#include "NodeType.h"
#ifndef LINKEDSTACK_H
#define LINKEDSTACK_H
template <class ItemType>
class LinkedStack {
public:
NodeType topPtr;
};
file: NodeType.h
#ifndef NODETYPE_H
#define NODETYPE_H
template <class ItemType>
class NodeType {
public:
ItemType info;
NodeType *nextElement;
};
#endif /* NODETYPE_H */
file: main.cpp
#include "NodeType.h"
#include "LinkedStack.h"
using namespace std;
int main(int argc, char** argv) {
return 0;
}
When I run this, I keep getting:
LinkedStack.h:20: error: `NodeType' does not name a type
However NodeType is already defined and included?
NodeType is a template. Change to:
NodeType<ItemType> topPtr;
Related
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 7 years ago.
I have a templated class named DataHandler
#ifndef DATAHANDLER_H
#define DATAHANDLER_H
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <set>
#include "constants.h"
template <typename T>
using Car = std::pair< T, T>;
template <typename T>
using SparseMatrix = std::vector< Car<T> >;
template <class T>
class DataHandler
{
public:
// initializes a new DataHandler only if none has been created,
// otherwise return the living instance
static DataHandler<T>* getInstance()
{
if(!dataHandler)
dataHandler = new DataHandler();
return dataHandler;
}
void readFile();
SparseMatrix<T>* getSparseBlue(){ return &sparseBlue; }
SparseMatrix<T>* getSparseRed(){ return &sparseRed; }
virtual ~DataHandler();
private:
// static DataHandler to ensure only one instance can be created
static DataHandler<T> *dataHandler;
// private constructor to use DataHandler as a Singleton
DataHandler();
int numElem = 0;
int m_rows, m_cols = -1;
#endif // DATAHANDLER_H
The source file is:
#include "data_handler.h"
#include <fstream>
#include <algorithm>
#include <omp.h>
#include <chrono>
using namespace std;
using namespace constants;
// Global static pointer used to ensure a single instance of the class.
template<typename T>
DataHandler<T>* DataHandler<T>::dataHandler = NULL;
template<typename T>
DataHandler<T>::DataHandler()
{
//ctor
}
template<typename T>
DataHandler<T>::~DataHandler()
{
//dtor
}
template<typename T>
void DataHandler<T>::readFile()
{
// do some stuff
}
// Instantiation of relevant templates
template class DataHandler<unsigned char>;
template class DataHandler<unsigned short int>;
In the last two lines I instantiate the templates which I define in main.cpp:
#include <iostream>
#include <chrono>
#include <fstream>
#include <algorithm>
#include "data_handler.h"
#include "dense_traffic_handler.h"
#include "sparse_traffic_handler.h"
#include "constants.h"
using namespace std;
// Check the number of rows/cols to choose between char or short int for the sparse case
bool matrixIsSmall()
{
return true;
}
void integerCase()
{
typedef unsigned char T;
DataHandler<T> *dh = DataHandler<T>::getInstance();
dh->readFile();
DenseTrafficHandler dth(dh); // ****** ERROR HERE *****
}
void charCase()
{
typedef unsigned char T;
DataHandler<T> *dh = DataHandler<T>::getInstance();
dh->readFile();
DenseTrafficHandler dth(dh); // ****** ERROR HERE *****
SparseTrafficHandler<T> sth;
set<unsigned short int> step = dh->getstep();
int currentStep = 0;
set<unsigned short int>::const_iterator stepToSave = step.begin();
}
int main(int argc, char *argv[])
{
if(matrixIsSmall())
charCase();
else
integerCase();
return 0;
}
Compiler gives me an error: undefined reference to DenseTrafficHandler::DenseTrafficHandler<unsigned short>(DataHandler<unsigned short>*)
DenseTrafficHandler header is like that:
#ifndef TRAFFICHANDLER_H
#define TRAFFICHANDLER_H
#include "constants.h"
#include "data_handler.h"
class DenseTrafficHandler
{
public:
template<typename T>
DenseTrafficHandler(DataHandler<T> *dh);
virtual ~DenseTrafficHandler();
private:
int m_cols, m_rows;
char* data;
char ** dense = NULL;
};
#endif // TRAFFICHANDLER_H
DenseTrafficHandler source is:
#include "dense_traffic_handler.h"
using namespace std;
using namespace constants;
template <typename T>
DenseTrafficHandler::DenseTrafficHandler(DataHandler<T> *datah)
{
DataHandler<T> *dh = datah;
dense = dh->getDense();
m_rows = dh->getm_rows();
m_cols = dh->getm_cols();
}
DenseTrafficHandler::~DenseTrafficHandler()
{
//dtor
}
So I have two questions:
Why do I receive this error and how can I manage it?
Is there a way in DataHandler source to not specify
template <typename T>
DataHandler<T>::functionName() for every function? (I mean something like using namespace Datahandler<T>)
You receive this error because compiler did not generate the code for this template type. One of solutions is to tell the compiler to do this explicitly by template instantiation:
add to your DenseTrafficHandler.cpp:
template class DenseTrafficHandler<unsigned short>;
Yes, just implement it in the header file. Reading more about it here.
Context: I've got a class Node like this:
#ifndef NODE_H_
#define NODE_H_
template <class T>
class Node
{
private:
T data;
Node* next;
Node* previous;
public:
Node();
Node(T);
~Node();
};
#endif /* NODE_H_ */
And a class ListDE like this:
/*
* ListDE.h
*
* Created on: Apr 22, 2013
* Author: x
*/
#ifndef LIST_H_
#define LIST_H_
#include <iostream>
#include <fstream>
#include <string>
#include "Node.h"
using namespace std;
template <class T>
class ListDE
{
private:
int qElements;
Node<T>* start;
Node<T>* getNextNode(Node<T>* aNode);
public:
ListDE();
~ListDE();
Node<T> getFirstPosition();
int getQNodes();
void setQNnodes(int q);
Node<T>* getNode(int pos);
T get_data(int pos);
void change_value(int pos, T newValue);
void add_new_data(T data);
void concat(ListDE<T>* otherList);
void delete_last();
};
#endif /* LIST_H_ */
Problem: when I try to compile, I get these errors:
ListDE.h:24:5: error: ‘Node’ is not a template
ListDE.h:26:5: error: ‘Node’ is not a template
ListDE.h:26:34: error: ‘Node’ is not a template
ListDE.h:32:5: error: ‘Node’ is not a template
ListDE.h:35:5: error: ‘Node’ is not a template
Can anyone explain to me what these mean? Thanks!
Add the following line to Node.h
#error Found the right Node.h
Then, adjust your include paths until you hit that error.
Finally, comment it out again.
I am trying to create a class linkedList using template but when I compile it the IDE gives an error :
undefined reference to `listType::add(int)
I am not understanding why ?
linkedList.h
#ifndef LINKEDLISTS_H_INCLUDED
#define LINKEDLISTS_H_INCLUDED
#include "struct.h"
template <class type1>
class listType
{
public:
void add(type1);
void print();
private:
node<type1> *head;
};
#endif // LINKEDLISTS_H_INCLUDED
LinkedList.cpp
#include "linkedLists.h"
#include "struct.h"
#include <iostream>
using namespace std;
template <class type1>
void listType<type1>::add(type1 temp)
{
node<type1> *t;
t->value=temp;
t->link=head;
head=t;
}
template <class type1>
void listType<type1>::print()
{
node<type1> *p;
p=head;
while(p!=NULL)
{
cout<<p->value<<endl;
p=p->link;
}
}
Struct.h
#ifndef STRUCT_H_INCLUDED
#define STRUCT_H_INCLUDED
template <class type1>
struct node
{
type1 value;
node *link;
};
#endif // STRUCT_H_INCLUDED
main.cpp
#include <iostream>
#include "linkedLists.h"
using namespace std;
int main()
{
listType <int> test;
test.add(5);
}
You can't have the implementation of templated classes and functions in the cpp file.
The code has to be in the header, so the including files can see the implementation, and instantiate the correct version with their template argument type.
I'm trying to create a linked list class in Eclipse but I can't get it to compile properly.
Here is my .cc file (code snipet)
#include <iostream>
#include "list.h"
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
and here is my list.h file (code snipet)
#ifndef __LIST_H__
#define __LIST_H__
template <typename T>
class List {
public:
bool isEmpty();
private:
struct node {
node *following;
node *previous;
T *contents;
};
node *firstNode;
};
#include "list.cc"
#endif /* __LIST_H__ */
I try "Building All" in eclipse but I get the following error:
make all
Building file: ../list.cc
Invoking: Cross G++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"list.d" -MT"list.d" -o "list.o" "../list.cc"
../list.cc:13: error: redefinition of 'bool List<T>::isEmpty()'
../list.cc:13: error: 'bool List<T>::isEmpty()' previously declared here
make: *** [list.o] Error 1
Help please...thanks. I'll be happy to provide any clarifications needed
EDIT: I was given the .h file so I know that it is correct. I also know that I am supposed to have a .cc file called list.cc (it is included at the end of the .h file)
You need to change the extension of the file with the implementation.
The compiler will process this file for compilation and will process it twice, since you're including it in the header.
Your file looks like this:
#include <iostream>
#include "list.h"
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
which will become
#include <iostream>
#ifndef __DLIST_H__
#define __DLIST_H__
template <typename T>
class List {
public:
bool isEmpty();
private:
struct node {
node *following;
node *previous;
T *contents;
};
node *firstNode;
};
#include "dlist.cc"
#endif /* __DLIST_H__ */
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
which will in turn become
#include <iostream>
#ifndef __DLIST_H__
#define __DLIST_H__
template <typename T>
class List {
public:
bool isEmpty();
private:
struct node {
node *following;
node *previous;
T *contents;
};
node *firstNode;
};
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
#endif /* __DLIST_H__ */
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
So the function isEmpty() is defined twice.
Rename the file to dlist.impl.
Try putting the definition for List<T>::isEmpty() in the same file as the class is declared.
Given the unusual form of the header you've been supplied with, to test it you will need another source file. To start with the new source file (say test.cpp) can just #include "list.h", which will check for any syntax errors but will not yet instantiate your List template.
(Just compile test.cpp, not list.cc, since list.cc is indirectly included by test.cpp)
#ifndef SLIST_H
#define SLIST_H
#include "llist.h"
using namespace std;
class slist:public llist{
public:
slist();
int search(el_t Key);
void replace(el_t Elem, int I);
};
#endif
That is my new class I just made that gives me the search and replace function, on top of all the inherited functions contained in llist.h
In my main...
#include "slist.h"
#include <iostream>
using namespace std;
int main(){
slist list;
list.addFront(4);
cout<<list.search(4);
}
I'm trying to call addfront() which is a public function in the llist class. Then I want to call search() which is an inherited public function of the slist class. g++ gives me a few errors that I don't understand.
slist.h: In function âint main()â:
slist.h:10: error: âslist::slist()â is protected
main.cpp:7: error: within this context
slist() is protected? Why's that? I put it under public:
Also whats up with the this context, I'm guessing I'm just doing the whole inheritance thing totally wrong. Any help would be appreciated!
Edit: Here's the llist class, if it helps
#ifndef LIST_H
#define LIST_H
#include <iostream>
using namespace std;
class llist{
protected:
typedef int el_t;
el_t total;
struct Node{
int Elem;
Node *Next;
};
Node *Front;
Node *Rear;
Node * Curr;
public:
class Overflow{};
class Underflow{};
class Range{};
llist();
~llist();
bool isEmpty();
void displayAll();
void addRear(el_t NewNum);
void deleteFront(el_t& OldNum);
void addFront(el_t NewNum);
void deleteRear(el_t& OldNum);
void deleteIth(int I, el_t& OldNum);
void addbeforeIth(int I, el_t newNum);
class Overflow;
};
#endif
This is llist.cpp with only the relevant functions pasted
#include "llist.h"
#include <iostream>
using namespace std;
int total=0;
llist::llist(){
Front=NULL;
Rear=NULL;
total=0;
}
llist::~llist(){
while(Front!=NULL){
int z;
deleteFront(z);
}
}
bool llist::isEmpty(){
if(Front==NULL){
return true;
}
return false;
}
void llist::displayAll(){
Curr=Front;
if(isEmpty()){
cout<<"[ empty ]"<<endl;
}else{
while(Curr!=NULL){\
cout<<"curr != NuL"<<endl;
cout<<Curr->Elem<<endl;
Curr=Curr->Next;
}
}
}
void llist::addFront(el_t NewNum){
if(isEmpty()){
Node *x=new Node;
x->Next=Front;
Rear=Front;
Front=x;
Front->Elem=NewNum;
}else{
Node *x=new Node;
x->Next=Front;
Front=x;
Front->Elem=NewNum;
++total;
}
}
I honestly can't see the problem but not every compiler is standard-compliant, so I would try the following:
1) Rename your class - if it works, that means it's a because of a naming conflict.
2) Remove the using directives.
3) Remove the inheritance. If it works after this... you really need to change compilers.
4) Try #undef public before your class declaration. If it works after this... well, someone's in for a talk with the manager.
5) Pray...