I had a redefinition problem but I noticed that I already included .cpp file in the .hpp file so my mistake was including the .hpp file in my .cpp file again
Now I am getting this error, something to do with templates.
Also while you fix my problem, can you explain to me what template class does?
cplusplus.com is not that descriptive.
Thank you. :)
//implementation
template<class T>
ArrayBag<T>::ArrayBag() : item_count_(0){}
-------------WARNING YOU ARE NOW LEAVING IMPLEMENTATION---------------------------
//interface
#ifndef ARRAY_BAG_H
#define ARRAY_BAG_H
#include <vector>
template<class T>
class ArrayBag
{
protected:
static const int DEFAULT_CAPACITY = 200;
T items_[DEFAULT_CAPACITY];
int item_count_;
int get_index_of_(const T& target) const;
public:
ArrayBag();
int getCurrentSize() const;
bool isEmpty() const;
//adds a new element to the end, returns true if it was successfully been added
bool add(const T& new_entry);
bool remove(const T& an_entry);
void clear();
bool contains(const T& an_entry) const;
int getFrequencyOf(const T& an_entry) const;
std::vector<T> toVector() const;
void display() const;
//overloading operators for objects
void operator+=(const ArrayBag<T>& a_bag);
void operator-=(const ArrayBag<T>& a_bag);
void operator/=(const ArrayBag<T>& a_bag);
};
#include "ArrayBag.cpp"
#endif
-------------WARNING YOU ARE NOW LEAVING INTERFACE---------------------------
//error
5 C:\Users\minahnoona\Desktop\ArrayBag.cpp expected constructor, destructor, or type conversion before '<' token
5 C:\Users\minahnoona\Desktop\ArrayBag.cpp expected `;' before '<' token
Don't call your ArrayBag.cpp a .cpp file. Template implementations go in header files, and the name should reflect that.
If you want the implementation in a separate file (you don't strictly need to), call it ipp or tpp. Something the project system won't try to compile on its own.
Then include it from the .hpp and don't include the .hpp from the .ipp.
Related
This question already has answers here:
Undefined reference to destructor error in c++?
(2 answers)
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 11 months ago.
I have a AVL class like this, it's templated and it gives error in main, I have tried to debug it for hours but it didn't fixed. What can be the problem? What part am I missing? It can be related to constructors but I tried that and it didn't fixed. I'm using Visual Studio 2012 and I feel stuck.
The error is:
1>Ege_HW2.obj : error LNK2019: unresolved external symbol "public: __thiscall AvlTree<struct item>::~AvlTree<struct item>(void)" (??1?$AvlTree#Uitem####QAE#XZ) referenced in function __unwindfunclet$??0AVLSection##QAE#XZ$0
1>Ege_HW2.obj : error LNK2019: unresolved external symbol "public: __thiscall AvlTree<struct AVLSection>::~AvlTree<struct AVLSection>(void)" (??1?$AvlTree#UAVLSection####QAE#XZ) referenced in function _main
1>fatal error LNK1120: 2 unresolved externals
Header file:
#ifndef AVLTREE_H
#define AVLTREE_H
#include <iostream>
#include <string>
using namespace std;
/* AVL Tree is taken from the lecture slides. */
template <class Comparable>
class AvlTree;
template <class Comparable>
class AvlNode
{
Comparable element;
AvlNode* left;
AvlNode* right;
int height;
AvlNode(const Comparable& theElement,
AvlNode* lt, AvlNode* rt, int h = 0)
: element(theElement), left(lt), right(rt), height(h) { }
friend class AvlTree<Comparable>;
};
template <class Comparable>
class AvlTree
{
public:
explicit AvlTree();
explicit AvlTree(const Comparable& notFound);
AvlTree(const AvlTree& rhs);
~AvlTree();
const Comparable& findMin() const;
const Comparable& findMax() const;
const Comparable& find(const Comparable& x) const;
bool isEmpty() const;
void printTree() const;
void makeEmpty();
void insert(const Comparable& x);
void remove(const Comparable& x);
const AvlTree& operator=(const AvlTree& rhs);
private:
AvlNode<Comparable>* root;
const Comparable ITEM_NOT_FOUND;
const Comparable& elementAt(AvlNode<Comparable>* t) const;
void insert(const Comparable& x, AvlNode<Comparable>*& t) const;
void remove(const Comparable& x, AvlNode<Comparable>*& t) const;
AvlNode<Comparable>* findMin(AvlNode<Comparable>* t) const;
AvlNode<Comparable>* findMax(AvlNode<Comparable>* t) const;
AvlNode<Comparable>* find(const Comparable& x, AvlNode<Comparable>* t) const;
void makeEmpty(AvlNode<Comparable>*& t) const;
void printTree(AvlNode<Comparable>* t) const;
AvlNode<Comparable>* clone(AvlNode<Comparable>* t) const;
// Avl manipulations
int height(AvlNode<Comparable>* t) const;
int max(int lhs, int rhs) const;
void rotateWithLeftChild(AvlNode<Comparable>*& k2) const;
void rotateWithRightChild(AvlNode<Comparable>*& k1) const;
void doubleWithLeftChild(AvlNode<Comparable>*& k3) const;
void doubleWithRightChild(AvlNode<Comparable>*& k1) const;
};
#include "AvlTree.cpp"
#endif
Cpp file:
#include "avlTree.h"
#include <iostream>
using namespace std;
template <class Comparable>
AvlTree<Comparable>::AvlTree(){
root = NULL;
}
/*** Construct the tree.
*/
template <class Comparable>
AvlTree<Comparable>::AvlTree(const Comparable& notFound)
:ITEM_NOT_FOUND(notFound), root(NULL){}
/*** Copy constructor.*/
template <class Comparable>
AvlTree<Comparable>::AvlTree(const AvlTree<Comparable>& rhs)
: root(NULL), ITEM_NOT_FOUND(rhs.ITEM_NOT_FOUND) {
*this = rhs;
}
And finally the main:
#include <iostream>
#include <string>
#include "BinaryTree.h"
#include "AvlTree.h"
#include <fstream>
using namespace std;
struct item{
string title;
string information;
item(){};
};
struct AVLSection{
AvlTree<item> avlSection;
string sectionTitle;
AVLSection(){};
};
struct BSTSection{
BinarySearchTree <item> bstSection;
string sectionTitle;
BSTSection(){}
};
void readData(BinarySearchTree<BSTSection> & bst, AvlTree<AVLSection> & avl){
ifstream input;
string filename = "data.txt",line;
input.open(filename.c_str());
while(getline(input,line)){
cout << line;
}
}
int main(){
BinarySearchTree<BSTSection> bst;
AvlTree<AVLSection> avl;
}
I am writing two templated classes (for academic reasons):
'class Vector', which mimics a C++ vector using a dynamic array.
'class Set', which creates a set using a vector object.
Vector.cpp -
#ifndef __CS_VECTOR_H_
#define __CS_VECTOR_H_
#include <cstdlib>
#include "Set.cpp"
template <class Type>
class Vector
{
public:
Vector(unsigned int capacity = DEFAULT_CAPACITY);
Vector(const Vector<Type>& rhs);
~Vector();
unsigned int capacity() const;
unsigned int size() const;
bool empty() const;
void push_back(const Type& data);
bool remove(const Type& data);
void clear();
bool at(unsigned int pos, Type& data) const;
int get_array_size() const;
Type& operator[](unsigned int pos) const;
Vector& operator=(const Vector& rhs);
private:
static const unsigned int DEFAULT_CAPACITY = 3;
void generate_larger_array(unsigned int capacity);
int array_size_ = 0;
int array_capacity_;
Type *array_;
};
//Function definitions here.
//#include "Set.cpp"
#endif
Set.cpp -
#ifndef __CS_SET_H_
#define __CS_SET_H_
#include "Vector.cpp"
template <class Comparable>
class Set
{
public:
unsigned int size() const;
bool empty() const;
bool contains(const Comparable& data) const;
bool insert(const Comparable& data);
bool remove(const Comparable& data);
void clear();
int get_size();
private:
int element_;
Vector<Comparable> set_;
};
//Function definitions here
//#include "Vector.cpp"
#endif
Main.cpp
#include "Set.cpp"
#include "Vector.cpp"
When I compile my code, I receive an error telling me:
error: ‘Vector’ does not name a type Vector<Comparable> set_;
When declaring my set_ object in Set.
These are both cpp files that are included into a file main.cpp. The set cpp file does contain the #include vector.cpp and vice versa
main.cpp just has code that tests the class functionality. I receive this error when attempting to compile either the main.cpp file. The main.cpp file is written by my instructor, so I am not entirely sure I should post it here.
Every time I create a new project in my workplace I run into the problem with templates. For example, I'll create a new class, which CodeLite will create a .h file and a .cpp file for me, and then I'll change that .cpp file into a .template by renaming the file. It sometimes works, and sometimes doesn't. Sometimes I have to clean my workplace for it to work, other times I need to exit out of CodeLite and reopen it. This time these solutions are not working for me, but maybe I am missing something. Here's my code:
.h file
#ifndef TABLE1_H
#define TABLE1_H
#include <cstdlib> // Provides size_t
namespace main_savitch_12A
{
template <class RecordType>
class table
{
public:
// MEMBER CONSTANT -- See Appendix E if this fails to compile.
static const std::size_t CAPACITY = 811;
// CONSTRUCTOR
table( );
// MODIFICATION MEMBER FUNCTIONS
void insert(const RecordType& entry);
void remove(int key);
// CONSTANT MEMBER FUNCTIONS
bool is_present(int key) const;
void find(int key, bool& found, RecordType& result) const;
std::size_t size( ) const { return used; }
private:
// MEMBER CONSTANTS -- These are used in the key field of special records.
static const int NEVER_USED = -1;
static const int PREVIOUSLY_USED = -2;
// MEMBER VARIABLES
RecordType data[CAPACITY];
std::size_t used;
// HELPER FUNCTIONS
std::size_t hash(int key) const;
std::size_t next_index(std::size_t index) const;
void find_index(int key, bool& found, std::size_t& index) const;
bool never_used(std::size_t index) const;
bool is_vacant(std::size_t index) const;
};
}
#include "table1.template" // Include the implementation.
#endif
.template file
template<class RecordType>
table<RecordType>::table(){
used = 32;
}
main file
#include <stdio.h>
#include "table1.h"
int main(int argc, char **argv)
{
printf("hello world\n");
return 0;
}
My template and my .h files are called table1. The error I am getting when I run the program is in the template file. It reads: "table does not name a type" How can I fix this issue?
In your template implementation your are missing the namespace, use this:
template <class RecordType>
main_savitch_12A::table<RecordType>::table()
{
used = 32;
};
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 7 years ago.
The solution to the duplicate question did not work
I have the following files:
ListaEnc.hpp
#include "Elemento.hpp"
template<typename T>
class ListaEnc {
public:
ListaEnc();
~ListaEnc();
// inicio
void adicionaNoInicio(const T& dado);
T retiraDoInicio();
void eliminaDoInicio();
T pegarHead();
// posicao
void adicionaNaPosicao(const T& dado, int pos);
int posicao(const T& dado) const;
T* posicaoMem(const T& dado) const;
bool contem(const T& dado);
T retiraDaPosicao(int pos);
// fim
void adiciona(const T& dado);
T retira();
// especifico
T retiraEspecifico(const T& dado);
void adicionaEmOrdem(const T& data);
// outras
bool listaVazia() const;
bool igual(T dado1, T dado2);
bool maior(T dado1, T dado2);
bool menor(T dado1, T dado2);
void destroiLista();
int pegarTamanhoLista();
private: //trocar pra private
Elemento<T>* head;
int size;
};
ListaEnc.cpp
#include "ListaEnc.hpp"
#include <cstdlib>
#include <iostream>
template<typename T>
ListaEnc<T>::ListaEnc()
{
...
}
main.cpp
#include "ListaEnc.hpp"
using namespace std;
int main(int argc, char** argv)
{
double x1, y1;
x1 = 2; y1 = 4.2;
ListaEnc<int>* teste = new ListaEnc<int>();
return 0;
}
This should compile just fine, but I get an undefined reference error to ListaEnc on main.cpp. I have more files in which the reference to ListaEnc is also undefined, but I tried isolating it and still can't get it to work. Does anyone understand why this is happening?
edit: More specifically, there is an undefined error to the constructor and destructor of ListaEnc
You can't separate declaration from implementation when you instantiate a template class. Combine your code to a single file and include that in your main.cpp.
Or, even go a step further and implement the functions inline in your class declaration if that suits your coding style.
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.