there are many solutions to this question bot nothing answers my case.
I am using VS 2008.I am tring to create a map using Binary search tree
#ifndef _map_h
#define _map_h
#include<string>
using namespace std;
template <typename ValType>
class Map
{
public:
Map();
~Map();
ValType getvalue(string key);
void add(string key,ValType value);
private:
struct node{
string key;
ValType value;
node *right;
node *left;
};
node *root;
node *treeSearch(string key,node *t);
void treeEnter(string key,ValType value,node *&t);
};
#include"map.cpp"
#endif
map.cpp
#include<string>
#include<iostream>
#include"map.h"
using namespace std;
template <typename ValType>
Map<ValType>::Map(){
root=NULL;
}
template <typename ValType>
Map<ValType>::~Map(){
delete root;
}
template <typename ValType>
ValType Map<ValType>::getvalue(string key){
node *found=treeSearch(key,root);
if(found==NULL)
cout<<"Couldnot Found the node";
else return found->value;
}
template <typename ValType>
typename Map<ValType>::node *Map<ValType>::treeSearch(string key,node *t){
if(t==NULL) return NULL;
if(t->key==key) return t;
if(t->key>key) treeSearch(key,t->left);
else treeSearch(key,t->right);
}
template <typename ValType>
void Map<ValType>::add(string key,ValType value){
treeEnter(key,value,root);
}
template <typename ValType>
void Map<ValType>::treeEnter(string key,ValType value,node *&t){
if(t==NULL){
t->value=value;
t->key=key;
t->left=NULL;
t->right=NULL;
}
else if(t->key==key) t->value=value;
else if(t->key>key) treeEnter(key,value,t->left);
else treeEnter(key,value,t->right);
}
Error:For all the functions its saying that they are already been defined.
I am following Stanford online course and the same worked for the instructor(she was using mac)
You have included map.h into map.cpp and map.cpp into map.h. The include guards in map.h will prevent multiple inclusion of map.h and will prevent infinite recursive inclusion. However, if you feed map.cpp to the compiler directly (which is what you are apparently trying to do) it will include map.h once and then map.h will include map.cpp itself one more time. This is what is causing the error.
If you want to implement your template as .cpp file included into .h file, you can do that. This is weird, but it can be forced to work. First and foremost, if you decided to #include your map.cpp, then don't even attempt to compile your map.cpp. Don't feed your map.cpp directly to the compiler. Also, remove #include "map.h" from that .cpp file. There's absolutely no point in doing that.
Your program will have other implementation files, like, say, myprogram.cpp, which will use your map. That myprogram.cpp should include map.h. That myprogram.cpp is what you will feed to the compiler. That way it will work as intended. But trying to compile map.cpp directly will only result in errors.
A better idea though would be not to put anything into a .cpp file. Either put everything into .h file or, if you really want to have it split that way, rename your .cpp file into something else to make it clear to everyone that this is not a translation unit.
In my case, I missed include guards or #pragma once at the top of the header where I defined a template function.
Related
I'm trying to understand how including works in C++. I have two questions about it. The first one is on how properly import the .h file. For example I created the following HashNode.h file:
namespace HashNode{
template<class Data>
class HashNode{
private:
Data data;
HashNode *next;
public:
explicit HashNode(const Data &data);
Data getKey();
~Node();
};
}
So in the HashNode.cpp file, it should like:
#include "HashNode.h"
using namespace HashNode;
template <class Data> // ~~~ HERE 1 ~~~
HashNode::HashNode(const Data &data) {//todo};
template <class Data> // ~~~ HERE 2 ~~~
Data* HashNode::getKey() {
//todo
}
HashNode::~Node() {
//todo
}
This way it works but do I have to include template <class Data> beside each function which uses Data? Why it does not recognize Data without including template <class Data>?
Also I have created the Hash.h file which should use the HashNode.h file:
#include "HashNode.h"
using namespace HashNode;
namespace Hash {
template <class Data>
class Hash {
typedef enum {
GOOD = 0,
BAD = -1,
BAD_ALLOC = -2
} Status;
private:
HashNode **hash;
int capacity;
int size;
public:
explicit Hash(int size);
Status insertData(const Data &data);
~Hash();
};
}
But I get the the following error: Can't resolve type 'HashNode'. Why it can't see the import?
In the Hash.cpp file I get Unused import statement for #include "HashNode.h". Why is that?
Also, what if I want to include private functions - should them be in the .h file or in the .cpp file?
The member functions of a template class are themselves also templates. Because of this, they need to be defined with any required template parameters and template type definitions.
About your second question, it has to do with namespaces. As I see it, having namespace and class under the same naming might cause you ambiguity. Although, everything seems to be fine on the structural side of the code. Try using #pragma once or some kind of guards to prevent this kind of issues.
I'm trying to create a stack using a linked list. I've already got it working using integers, but now I want to implement Templates to it. There are no errors detected before compile, but after running I get these errors:
*Undefined symbols for architecture x86_84:
"Stack::printStack()", referenced from:
_main in main.o
"Stack::pop()", referenced from:
_main in main.o
"Stack::push(int)", referenced from:
_main in main.o
"Stack::~Stack()", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
*
I think my troubles come from having to define two templates, one in the Stack.h file and one in my LinkedList.h file. In my Stack.h file I need to call on Node, I can't call on Node without including the template arguments, and Stack.h won't recognize the template arguments without me including another template definition. Right now there are instances where I only use 'T' instead of Node, but I've tried it both ways. I feel like I've tried everything and I just can't figure out where my error is. I'm really just going for proof of concept at this point which is why I haven't added a copy constructor or additional functions for Stack. My code is below.
LinkedList.h
#ifndef Linked_List__Stack_LinkedList_h
#define Linked_List__Stack_LinkedList_h
template<class T>
struct Node {
public:
Node(Node *n, T data) : next(n), data(data) {}
Node *getNext() const { return next; }
T value() const { return data; }
private:
Node* next;
T data;
};
#endif
Stack.h
#ifndef __Linked_List__Stack__Stack__
#define __Linked_List__Stack__Stack__
#include "LinkedList.h"
#include <stdio.h>
#include <iostream>
using namespace std;
template <class T>
class Stack {
public:
Stack() : head(NULL), tail(NULL) {};
~Stack();
void push(T data);
T pop();
void printStack();
private:
Node<T> *head;
Node<T> *tail;
};
#endif /* defined(__Linked_List__Stack__Stack__) */
Stack.cpp
#include "Stack.h"
template <class T>
Stack<T>::~Stack() {
while (head) {
Node<T>* temp = head->getNext();
delete head;
head = temp;
}
head = tail = NULL;
}
template <class T>
void Stack<T>::push(T data) {
Node<T>* node = new Node<T>(head, data);
head = node;
if (head->getNext() == NULL )
tail = head;
}
template <class T>
T Stack<T>::pop() {
Node<T> *top = head;
T data;
if(head == NULL)
throw; //StackError(E_EMPTY);
data = head->value();
head = head->getNext();
delete top;
return data;
}
template <class T>
void Stack<T>::printStack() {
Node<T> *current = head;
while (current != tail) {
cout << current->value() << ", ";
current = current->getNext();
}
cout << current->value() << endl;
}
main.cpp
#include "Stack.h"
#include <iostream>
#include <stdexcept>
int main(int argc, const char * argv[]) {
Stack<int> *myIntStack = new Stack<int>();
myIntStack->push(10);
myIntStack->printStack();
myIntStack->pop();
myIntStack->printStack();
delete myIntStack;
return 0;
}
Almost no popular compiler allow you to put template definition in cpp file as a separated compilation unit (hence the linker errors).
In brief, just move the content of your Stack.cpp into Stack.h (and forget about your Stack.cpp) then everything should work.
Another way I like to use (well... over ten years ago when I am still writing C++ in my job), is to "include" the template source in the header, like:
Foo.h
#ifndef FOO_H__
#define FOO_H__
TEMPLATE_DECL template <class T> Foo {
....
};
#ifndef SUPPORT_TEMPLATE_EXPORT
#include "Foo.tmpl" // include it if you CANNOT compile it as separate compilation unit
#endif
#endif //ifndef FOO_H__
Foo.tmpl (I use another extension to differ it from .cpp)
#ifdef SUPPORT_TEMPLATE_EXPORT
#include "Foo.h" // only include if you can compile it as separate compilation unit
#endif
// template definition
TEMPLATE_DEF Foo<T>::bar() {....}
Of course you need to take care of the preprocessor and compiler setup but that should be trivial. And, template export is deprecated from C++0x, this approach can be further simplified if you are not care about using this feature in older compiler (e.g. Comenu)
Something off-topic: Avoid using namespace (or any using clause in fact) in your headers. It is going to cause namespace pollution.
As Adrian points out, the compiler needs to have all the template implementation available to it at instantiation time, and I agree with his suggestion to simply move the implementation into Stack.h.
However, if you want to keep interface and implementation separate for your own purposes, you can #include "Stack.cpp" at the bottom of Stack.h (and remove the #include "Stack.h" from Stack.cpp).
Anybody know how I can fix these errors?
i have been looking at it for a while and just cannot figure out what to do.
Error:
indexList.cpp:18: error: redefinition of `indexList<T>::indexList()'
indexList.cpp:18: error: `indexList<T>::indexList()' previously declared here
indexList.cpp:30: error: redefinition of `bool indexList<T>::append(T)'
indexList.cpp:30: error: `bool indexList<T>::append(T)' previously declared here
cpp file:
//
//
//
//
//
//
#include "indexList.h"
#include <iostream>
using namespace std;
//constuctor
//Descriptions: Initializes numberOfElement to 0
// Initializes maxSize to 100
//Parameters: none
//Return: none
template <class T>
indexList<T>::indexList()
{
numberOfElements = 0;
maxSize = 100;
}
//Name: append
//Purpose: Adds element to the end of the list. If array is full, returns false
//Paramters: value - thing to append
//Return: true if append succeeds, false otherwise
template <class T>
bool indexList<T>::append(T value)
{
if (maxSize > numberOfElements)
{
list[numberOfElements] = value;
numberOfElements ++;
return true;
}
else
return false;
}
I didn't put all the the cpp file because the rest of the errors are similar to the ones above, and it is quite long
header:
#include <iostream>
using namespace std;
#ifndef INDEXLIST_H
#define INDEXLIST_H
template <class T>
class indexList
{
public:
indexList();
bool append(T value);
bool insert(int indx, T value);
bool replace(int indx, T newValue);
bool retrieve(int indx, T &value) const;
bool remove(int indx);
void sort();
int search(T value) const;
private:
T list[100];
int numberOfElements;
int maxSize;
};
template <class T>
ostream &operator<<(ostream &outStream, const indexList<T> &lst);
#include "indexList.cpp"
#endif
I did put the entire header
Each of your two files tries to include the other, which can cause the preprocessor to output some repeated code.
Take the #include "indexList.h" out of the file indexList.cpp.
Also, your build process should not attempt to compile indexList.cpp into an object file.
Another way to arrange things would be to just put all the contents you currently have in indexList.cpp near the end of indexList.h, and there would be no indexList.cpp file at all.
What you've done is ok, but you must realise that the .cpp file should not itself be compiled into an object - instead, just include the .h file from your application code:
// main.cc
#include "indexList.h"
int main()
{
indexList<int> il;
}
c++ -o main main.cc
I'd bet it's because you've tried to do a c++ -c indexList.cpp or c++ indexList.cpp that you get the errors (or perhaps your make tool is trying that automatically for all .cpp files in your source code directories - you could try renaming indexList.cpp to indexList.inl or .inc or whatever - remember to change the name in indexList.h too - to see if that fixes the problem), as in that situation the definitions are seen twice: once as the compile includes indexList.h, and again as it finishes compiling indexList.cpp.
There's no need to include indexList.h from within the .cpp anyway - that makes it look as if the indexList.cpp is designed for separate compilation.
Put any of your templated methods in an indexList.inl file, and include that from your header. Don't include the header from this file.
Put any other methods in your indexList.cpp file. Include the header from this file.
I want to write a program in C++ with separate compilation and I wrote this:
main.cpp
#include <iostream>
#include "Stack.h"
using namespace std;
int main(int argc,char* argv[])
{
Stack<int> st;
st.push(1);
return 0;
}
Stack.h
#ifndef _STACK_H
#define _STACK_H
template<typename T>
class Stack
{
private:
struct Node
{
Node* _prev;
T _data;
Node* _next;
};
int _size;
Node* _pos;
public:
Stack();
T pop();
void push(T const &el);
int getSize() const;
};
#endif
Stack.hpp
#include "Stack.h"
#include <malloc.h>
template <typename T>
Stack<T>::Stack()
{
_size = 0;
_pos = (Node*)malloc(sizeof(Node));
_pos->_prev = NULL;
_pos->_next = NULL;
}
template <typename T>
T Stack<T>::pop()
{
if (_size == 0)
return NULL;
T tmp = _pos->_data;
if (_pos->_prev == NULL)
free(_pos);
else
{
_pos->_prev->_next = _pos->_next;
if (_pos->_next != NULL)
{
_pos->_next->_prev = _pos->_prev;
}
free(_pos);
}
_size--;
return tmp;
}
template <typename T>
void Stack<T>::push(T const &el)
{
Node* n = (Node*)malloc(sizeof(Node));
_pos->_next = n;
n->_prev = _pos;
n->_data = *el;
_pos = n;
_size ++;
}
template<typename T>
int Stack<T>::getSize() const {return _size;};
I compiled the program with g++ and I get this error:
ccyDhLTv.o:main.cpp:(.text+0x16): undefin
ed reference to `Stack<int>::Stack()'
ccyDhLTv.o:main.cpp:(.text+0x32): undefin
ed reference to `Stack<int>::push(int const&)'
collect2: ld returned 1 exit status
I know that the problem is because I'm using templates but I do not know how to fix it.
OS - Windows
compilation line - g++ main.cpp Stack.h Stack.hpp -o main.exe
Template classes need to have the method definitions inside the header file.
Move the code you have in the .cpp file inside the header, or create a file called .impl or .imp, move the code there, and include it in the header.
The compiler needs to know the method definitions to generate code for all specializations.
Before you ask, no, there is no way to keep the implementation outside the header.
I would say it will be more pragmatic to first understand how separate compilation works for normal (untempelated) files and then understand how g++ compiler does it for template.
First in normal files, when the header file containing only the declarations are #included in main file, the preprocessor replaces the declarations from the header and puts it to the main file. Then after the preprocessing phase is over, the compiler does one by one compilation of the pure C++ source code contained in .cpp files and translates it into object file. At this point the compiler doesn't mind the missing definitions (of functions/classes) and the object files can refer to symbols that are not defined. The compiler, hence can compile the source code as long as it is well formed.
Then during the linking stage the compiler links several files together and it is during this stage the linker will produce error on missing/duplicate definitions. If the function definition is correctly present in the other file then the linker proceeds and the function called from the main file is successfully linked to the definition and can be used.
For templates, things work differently. It will be illustrative to consider an example, so I pick a simple one:
consider the header file for template array class:
array.h
#ifndef _TEMPLATE_ARRAY_H_
#define _TEMPLATE_ARRAY_H_
template <class T>
class Array
{
private:
T *m_list;
int m_length;
public:
Array() //default constructor
{
m_list = nullptr;
m_length = 0;
}
Array(int length)
{
m_list = new T[length];
m_length = length;
}
~Arrary()
{
delete[] m_list;
m_list = nullptr;
}
//undefined functions
int getLength();
T getElement(const int pos);
};
and the corresponding array.cpp file :
include "array.h"
template <class T>
array<T>::getLength()
{ return m_length; }
template <class T>
T Array<T>::getElement(const int pos)
{ return m_list[pos]; }
Now consider the main file where two instances of the templated object array, one for int and another for double is created.
main.cpp
#include "array.h"
#include <iostream>
int main()
{
Array<int> int_array;
Array<double> double_array;
std::cout << int_array.getLength() <<"\n";
std::cout << double_array.getLength() << "\n";
}
When this piece of code is compiled, the preprocessor first copies the template declarations from the header file to the main file as usual. Because in the main file Array< int > and Array< double > objects are instantiated, compiler instantiates two different definitions of Array class, one each for double and int and then instantiate the Array objects in the main.cpp file.
Note till this point the function definitions for Array< int >::getLength() and Array< double >::getLength() is still missing in the main.cpp file but since the source code is well formed the compiler compiles the main.cpp file without any hassle. In short there's no difference b/w templated object/function compilation and non-templated function compilation till now.
In the meanwhile the code file for array.cpp containing the template function definitions for Array< T >::getLength() and Array< T >::getElement() is compiled, but by this time the compiler would have forgotten that main.cpp needs Array< int >::getLength() and Array< double >::getLength() and would happily compile the code array.cpp without generating any instances for int and double version of the function definition needed by the main.cpp file. (Remember that compiler compiles each file separately!)
It is during the linking phase horrible template errors start popping because of the missing function definitions for int and double version of template function definition that are required by the main file. In the case of non-template declarations and definitions, the programmer makes sure to define the sought function in a file which can be linked together with the file calling the function. But in the case of templates, the linker which executes after the compilation phase, cannot do a task that a compiler is suppose to do, i.e generate a code, in this case for int and double type of the template function
There are ways to get around this
Having gone through the entire story, one can easily conclude that the entire fuss up around template separate compilation is due to linkage (i.e) if all codes are written correctly, class and functions declared in header and defined in another separate file). Ways of getting around this are :
Define the class and functions in the header files themselves rather than in separate file so that the contents of header file when included in the main file, includes the templated definitions which cause appropriate instances of necessary functions to be defined by the compiler.
Instantiate the type definitions you know you will need in the separate file where the template definitions are written. This will then directly be linked to the function calls in the main file.
Another way to get around this is to name the .cpp file where definitions are written to .inl* file (from the e.g drawn above, chagne array.cpp to array.inl); inl means inline and include the .inl file from the bottom of the header file. This yields the same result as defining all functions within the header file but helps keeping the code a little cleaner.
There's another way, i.e #include .cpp file with templated definitions in the main file which I personally don't prefer because of non-standard usage of #include.
It is absolutely possible to have templates and separate compilation, but only if you know in advance for which types the template will be instantiated.
Header file sep_head.h:
template< typename T >
class sep{
public:
sep() {};
void f();
};
Main:
#include "sep_head.h"
int main() {
sep<int> s; s.f();
sep<double> sd; sd.f();
sep<char> sc; sc.f();
return 0;
}
Implementation:
#include "sep_head.h"
template< typename T >
void sep<T>::f() {}
template class sep<int>;
template class sep<double>;
template class sep<char>;
I've defined a template class like so (providing .hpp file):
#ifndef PERSOANLVEC_H_
#define PERSOANLVEC_H_
#include <vector>
using namespace std;
template<class T, class PrnT> class PersoanlVec {
public:
PersoanlVec();
~PersoanlVec();
void push_back(T t);
void erase(int index);
PersoanlVec& operator[](int index);
const PersoanlVec& operator[](int index) const;
void print() const;
size_t size();
private:
vector<T> _vector;
};
#endif /* PERSOANLVEC_H_ */
Now, everything compiles ok with this class. When I try to use it I get
undefined reference to PersoanlVec<Person, Person>::PersoanlVec()'.
Here's where I call it:
#include "Person.h"
#include "PersoanlVec.hpp"
#include <cstdlib>
int main(void)
{
Person p1("yotam");
Person p2("yaara");
PersoanlVec<Person,Person> *a = new PersoanlVec<Person,Person>(); //<---ERROR HERE
return EXIT_SUCCESS;
}
This is my first try with templates, its not very clear for me obviously. I DO have a constructor with no parameters, Any ideas?
Thanks!
Do you have the content of your constructor and functions in a .cpp file? If yes, there's your problem. Put them in the header file, possible just inline in the class itself:
template<class T, class PrnT> class PersoanlVec {
public:
PersoanlVec(){
// code here...
}
~PersoanlVec(){
// code here...
}
void push_back(T t){
// code here...
}
void erase(int index){
// code here...
}
PersoanlVec& operator[](int index){
// code here...
}
const PersoanlVec& operator[](int index) const{
// code here...
}
void print() const{
// code here...
}
size_t size(){
// code here...
}
private:
vector<T> _vector;
};
For the reason, have a look here.
I am pretty sure you just forgot to add the file to the compilation process. Be careful with your misspelling, since that can cause generic pain.
Whenever you have different compilation units (classes for example, each with their .h/.cpp), your classes need to know of the interfaces, reason for which you normally include the header files, yet the compiler also needs to know the implementations so that it can bind together your binary file.
As such, you will need to call the compiler passing all the .cpp files in your project to it, otherwise it will fail letting you know you are referencing unimplemented pieces.
You need to have all of your template function definitions held in the header file rather than the CPP file - this is basically because the template definition will be used multiple times to create multiple types depending on what parameters you pass in to it as type parameters around your code. The only template related functions that should ever be defined in the CPP file are template specialization functions - those where you want to explicitly say (if user passed in type A and B then do this specifically instead of the default action).