C++ undefined reference to class that uses template [duplicate] - c++

This question already has answers here:
Why do I get "unresolved external symbol" errors when using templates? [duplicate]
(3 answers)
Closed 9 years ago.
I'm pretty new with templates, so please don't be harsh on me if my code is very wrong :)
This is the header file for a class Key that uses a template:
//Key.h
#ifndef KEY_H
#define KEY_H
#include "../Constants.h"
template<class KeyType>
class Key
{
public:
Key<KeyType>(KeyType initial);
KeyType increment();
private:
KeyType current;
};
#endif /* KEY_H */
This is the .cpp file of Key class:
//Key.cpp
#include "Key.h"
template<class KeyType> Key<KeyType>::Key(KeyType p_initial)
{
this->current = p_initial;
}
template<class KeyType> KeyType Key<KeyType>::increment()
{
this->current ++; //KeyType should implement this operator
}
So what's the problem? I try to create an instance of Key somewhere else in my code, like this:
Key songID (0); // ERROR: undefined reference to Key<int>::Key(int)
and then use
songID.increment(); // ERROR: undefined reference to Key<int>::increment()

Two points:
Remove <KeyType> from Key<KeyType>(KeyType initial); you don't need it.
And, move class implementation from .cpp file to .h file. Thie article is useful: Why can't I separate the definition of my templates class from its declaration and put it inside a .cpp file?

Related

Undefined reference to struct method [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 3 years ago.
I tried to make an Array template class but when I try to build the compiler fails to link the constructor and the method and I get :
undefined reference to `Array::Array()
undefined reference to `Array::getSize()
Here is the header file:
#pragma once
template<typename type, int length>
struct Array{
public:
Array();
int getSize();
private:
type data[length];
int m_length;
};
The Array.cpp file:
#include "Array.h"
template<typename t, int l>
Array<t, l>::Array()
{
m_length = l;
}
template<typename type, int length>
Array<type, length>::getSize()
{
return m_length;
}
And the main function:
#define LOG(x) cout<<x<<endl
int main()
{
Array<int, 10> array;
LOG(array.getSize());
}
If someone has any idea about why I am getting this, I would really appreciate.
You need to either put your implementation into the header files, or define the usage (instantiation of the template arguments) in the source file

unqualified-id error before ')' token [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 6 years ago.
I am new to stack overflow and I would appreciate feedback. I am creating a template graph class and have split it into two files graph.h and graph.hpp, but everytime I compile I get this error:
In file included from graph.h:97:0,
from main.cpp:2:
graph.hpp:4:26: error: expected unqualified-id before ‘)’ token
typename graph<T>::graph(){
^
makefile:2: recipe for target 'executable.x' failed
Here is my graph.hpp file so far:
#include "graph.h"
//template <typename T>
typename graph<T>::graph(){
numVertices = 0;
graphWeight = 0;
}
And my graph.h file looks something like:
template <typename T>
class graph{
public:
graph();
.
.
.
private:
};
Also, my main.cpp is just simply:
#include "graph.h"
int main(){
graph<int> g;
}
What could possibly be wrong? I know it's probably something simple that has to do with the template.
Thanks
In your graph.hpp snippet, change your code to this
#include "graph.h"
template <typename T>
graph<T>::graph(){ //Constructor has no return type.
numVertices = 0;
graphWeight = 0;
}
Unfortunately, you have cannot really have separate header and implementation file for templates, so put the implementation in your header file. For more info and workarounds, see Why can templates only be implemented in the header file?

compile header files defines a template class which also includes other header files [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
JUST to make it clear : it is different from the problem that we must define functions of template class in the header file.
UPDATE : if you need the real source code, you can download it here : https://Near#bitbucket.org/Near/compile_error.git
I implement a double list class.
// list.h //
class list {
//...
void insert(...);
};
// list.cpp //
#include "list.h"
void list::insert(...) {
...
}
I also implement a template class which include the list.h
// template_class.h //
#include "list.h"
template<class T>
class temp_class {
list l;
void func();
}
void temp_class::func() {
//...
l.insert(...);
}
Now I write a test.cpp file which include the template_class.h and call the func function
// test.cpp //
#include "template_class.h"
int main() {
temp_class<int> t;
t.func();
return 0;
}
I compile like this
g++ test.cpp list.cpp -o test
The compiler complains that test.cpp : "undefined reference to insert".
Why can't it work? How to solve this error?
FYI : If I include the content in list.cpp in list.h and just compile test.cpp, it works. But I don't think it is a good idea.
When compiling your code I immediately get the warning:
list_double.h:14:15: warning: inline function ‘void list_double_node::list_double_insert_first(list_double_node*)’ used but never defined [enabled by default]
void inline list_double_insert_first(list_double_node* entry);
That is, your code is actually akin to this SSCCE:
// list.h
class list {
public:
inline void insert(int);
};
.
// list.cpp
#include "list.h"
void list::insert(int) {
}
.
// template_class.h
#include "list.h"
template<class T>
class temp_class {
list l;
public:
void func();
};
template <class T>
void temp_class<T>::func() {
l.insert(17);
}
.
// test.cpp
#include "template_class.h"
int main() {
temp_class<int> t;
t.func();
return 0;
}
The fix is: either remove the inline or define the function in the header. The rules for inline are actually pretty much the same as those for template: whenever an inline function is used, its implementation has to be provided.

error C2995:function template has already been defined

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.

using template declared in other file in c++ [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can templates only be implemented in the header file?
What is an undefined reference/unresolved external symbol error and how do I fix it?
I have defined a template class in a file.
point.h is
#ifndef POINT_H
#define POINT_H
using namespace std;
template <typename T, int size>
class point {
private:
T coordinates[size];
public:
point();
void set_coordinates(const T *);
void get_coordinates(T *);
};
#endif /* POINT_H */
point.c is
#include "point.h"
template <typename T, int size>
point::point() {
for (int i = 0; i < size; i++)
coordinates[i] = 0;
}
template <typename T, int size>
void point<T, size>::set_coordinates(const T *coordinates) {
for (int i = 0; i < size; i++)
this->coordinates[i] = coordinates[i];
}
template <typename T, int size>
void point<T, size>::get_coordinates(T *coordinates) {
for (int i = 0; i < size; i++)
coordinates[i] = this->coordinates[i];
}
I am using this template as point<int, 2> p0;. But compiler gives error that point<int, 2> is not defined.
I searched on this and found two solutions -
1. to use export variable. But I read that it is not supported by all compilers. So, I don't want to use that.
2. to create explicit class specializations like
template <> class point<int> {
...
}
But isn't there any other way to do this? (I mean in C++ standard containers, they might have used some technique to do this.)
Read this and the next two FAQ questions - C++ FAQ
The solution of the c++ standard containers is keep everything in the header file.
You should put all the definitions belonging to the template point (that is, including the member functions) to the point.h file and include it in any file that uses the point class, so that the compiler can instantiate it as needed. See this question for details.
The C++ compilers and linkers have means to avoid "multiple definitions" error on link (the ODR rule in the standard states this must be the case).