c++ undefined reference to function [duplicate] - c++

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 8 years ago.
I'm trying to implement a generic Queue class.
The Template class looks like it:
Queue.h
template <class T>
class Queue {
public:
Queue() {}
~Queue() {}
...
void enqueue( const T& e );
T dequeue( void );
int Size( void ) const { return s1.size() + s2.size();}
private:
std::stack<T> s1;
std::stack<T> s2;
};
#include "Queue.cpp"
And the implementation of it looks like it:
Queue.cpp:
#include "Queue.h"
template <class T>
void Queue<T>::enqueue( const T& e )
{
//...
}
template <class T>
T Queue<T>::dequeue ()
{
//...
}
my Problem is, i can't call some function of this class whtich I've implemented in the file Queue.cpp.
main.cpp:
int main() {
Queue<int> myQueue;
const int a = 1;
myQueue.enqueue(a);
myQueue.Size();
return 0;
}
i become always the follwing erro:
undefined reference to Queue::enqueue(int const&)
[Error] ld returned 1 exit status
Makefile.winrecipe for target 'MYQueue.exe' failed

Place the whole template definition including its member functions in one header file.

Related

How can I get rid of the <error-type> type that is appearing in my method template? Both the input to the method and the class are templates

I am getting the error
declaration is incompatible with "void spectrogram<T>::update(<error-type> x)
I don't see any difference between the declaration and the definition of the method, not sure why it is complaining about just this one definition and not the constructor or destructor.
Here is vComplex.hpp
#ifndef VCOMPLEX_H
#define VCOMPLEX_H
template <class T>
class vComplex {
public:
T* realp;
T* imagp;
int length; // for bookkeeping
vComplex(void) { }
vComplex (T* I, T* Q, int len) {
realp = I;
imagp = Q;
length = len;
}
~vComplex(void) {
free(realp);
free(imagp);
}
void put(T* I, T*Q, int len) {
realp = I;
imagp = Q;
length = len;
}
};
#endif
the function declaration for update in spectrogram.hpp, with other members removed:
#ifndef SPECTROGRAM_H
#define SPECTROGRAM_H
template <typename T>
class spectrogram {
public:
void update(vComplex<T> x);
};
#endif
and the function signature (and includes) for update in spectrogram.cpp:
#include <stdio.h>
#include <math.h>
#include "spectrogram.hpp"
#include "vComplex.hpp"
template <typename T>
void spectrogram<T>::update(vComplex<T> x) {
//do stuff
}
In VS 2017, I get the red underline under update and everything inside of it breaks basically. VS is saying T is undefined which I'm assuming is caused by the overall error. I have to use dynamically allocated pointers, I don't have the option of using other types or containers.

Cannot solve "Undefined reference to ..." Error [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 8 years ago.
There is a problem with this code and I can't understand it.
It seems the problem happens within the linking phase as I've googled, but in my case I think there is something wrong with my code, not in toolchains, but I just couldn't solve it after hours and hours of trying. I'd be happy if you help me correcting it.
I'm using Code::Blocks, and the latest version of MinGW.
main.cpp
#include <iostream>
#include <string>
#include "threadsafequeue.hpp"
using namespace std;
int main(){
threadsafe_queue<string> Q;
threadsafe_queue<string> X;
X.empty();
try{
string s;
}catch(empty_queue ex){
cout << ex.what() << endl;
}
return 0;
}
threadsafe_queue.cpp
#include "threadsafe_queue.hpp"
template <typename T>
threadsafe_queue<T>::threadsafe_queue(const threadsafe_queue& other){
std::lock_guard<std::mutex> lock(other.m);
threadsafe_queue<T>::data = other.data;
}
template <typename T>
void threadsafe_queue<T>::push(T new_value){
std::lock_guard<std::mutex> lock(threadsafe_queue<T>::m);
threadsafe_queue::data.push(new_value);
}
template <typename T>
std::shared_ptr<T> threadsafe_queue<T>::pop(){
std::lock_guard<std::mutex> lock(threadsafe_queue<T>::m);
if(data.empty()) throw empty_queue();
std::shared_ptr<T> const res(std::make_shared<T>(threadsafe_queue<T>::data.front()));
threadsafe_queue<T>::data.pop();
return res;
}
template <typename T>
void threadsafe_queue<T>::pop(T& value){
std::lock_guard<std::mutex> lock(threadsafe_queue::m);
if(data.empty()) throw empty_queue();
value = threadsafe_queue::data.front();
threadsafe_queue::data.pop();
}
template <typename T>
bool threadsafe_queue<T>::empty(){
std::lock_guard<std::mutex> lock(threadsafe_queue<T>::m);
return threadsafe_queue<T>::data.empty();
}
threadsafe_queue.hpp
#include <exception>
#include <memory>
#include <mutex>
#include <queue>
#ifndef THREADSAFE_QUEUE_HPP_INCLUDED
#define THREADSAFE_QUEUE_HPP_INCLUDED
struct empty_queue : std::exception
{
virtual const char * what() const throw()
{
return "The Queue is Empty.";
};
};
template <typename T>
class threadsafe_queue
{
private:
std::queue<T> data;
mutable std::mutex m;
public:
threadsafe_queue() {};
threadsafe_queue(const threadsafe_queue& other);
threadsafe_queue& operator= (const threadsafe_queue&) = delete;
void push(T new_value);
std::shared_ptr<T> pop();
void pop(T& value);
bool empty();
};
#endif // THREADSAFE_QUEUE_HPP_INCLUDED
And the error is :
...\ThreadSafeQueue\main.cpp|9|undefined reference to
`threadsafe_queue::empty()'|
Move everything from threadsafe_queue.cpp to threadsafe_queue.hpp.
Why can templates only be implemented in the header file?
Or, if you want declaration and implementation of template to be separated, rename threadsafe_queue.cpp to threadsafe_queue.tpp (not really needed, just for better clarity) and include it at the end of threadsafe_queue.hpp file.
You must include in your main.cpp also your implementation file:
threadsafe_queue.cpp
actually your template definitons must be in your threadsafe_queue.hpp file otherwise templates will not be instantiated.

Linker error : unsolved external symbol [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 9 years ago.
I'm trying to create a template c++ Stack, and i'm having some issue with the linker.
I've tried to put all the classes into one cpp file, and it works just fine, but the problem begin once I separate them into different files
here's my classes
main class :
#include <iostream>
#include "stack.h"
using namespace std;
int main()
{
Stack<double>* st = new Stack<double>();
st->push(new Data<double>(10));
cout << st->pop()->getData();
return 0;
}
stack.h :
#ifndef STACK_H
#define STACK_H
#include "data.h"
template <class T>
class Stack
{
public:
Stack():_current(NULL){}
void push(Data<T>* const);
Data<T>* pop();
private:
Data<T>* _current;
};
#endif;
stack.cpp :
#include "stack.h"
template <class T>
Data<T>* Stack<T>::pop()
{
if(this->_current == NULL)
{
cout << "Empty stack." <<endl;
return NULL;
}
else
{
Data<T>* tmpPtr = this->_current;
this->_current = this->_current->getPrev();
return tmpPtr;
}
}
template <class T>
void Stack<T>::push(Data<T>* const data)
{
if(this->_current == NULL) // Empty stack;
{
_current = data;
_current->setPrv(NULL);
}
else
{
Data<T>* tmpPtr = this->_current;
this->_current = data;
this->_current->setPrv(tmpPtr);
}
}
data.h
#ifndef DATA_H
#define DATA_H
template <class T>
class Data
{
public:
Data(T data):_data(data){}
T getData() const { return this->_data; }
void setPrv(Data* const prev){ this->_prev = prev; }
Data* getPrev() const { return this->_prev; }
private:
Data<T>* _prev;
T _data;
};
#endif
Put all the definitions of the template class functions in the .h. They basically aren't allowed to be in separate files.
This occurs becauses templates are not like typical classes. The compiler will generate a class for you off of your template instantiation. Because of this, the compiler will need to know where to lookup the function definitions, so put them inside the .h where the class is defined.
Template functions are not compiled until they're specialized(used), and your stack.cpp doesn't produce any machine code. Move them to stack.h

Linking error with template classes

I have a class that needs to call an external function in a variety of different contexts. I want to keep things flexible, so I'm using an interface (inspired by the 3rd edition of Numerical Recipes) that should work with functors, function pointers, etc. A simplified example looks like:
class MyClass {
public:
template <class T>
MyClass(T &f_) { f = f_; }
private:
int (*f)(int);
};
int myFn(int i) {
return i % 100;
}
int main() {
MyClass test(myFn);
return 0;
}
So far so good; g++ compiles this without any complaints. In my real application, there's a lot more code so I've got things split up among multiple files. For example,
test2.h:
#ifndef __test2__
#define __test2__
class MyClass {
public:
template <class T>
MyClass(T &f_);
private:
int (*f)(int);
};
#endif
test2.cpp:
#include "test2.h"
template <class T>
MyClass::MyClass(T &f_) {
f = f_;
}
main.cpp:
#include "test2.h"
int myFn(int i) {
return i % 100;
}
int main() {
MyClass test(myFn);
return 0;
}
When I try to compile this using g++ test2.cpp main.cpp, I get the following linking error:
/tmp/ccX02soo.o: In function 'main':
main.cpp:(.text+0x43): undefined reference to `MyClass::MyClass<int ()(int)>(int (&)(int))'
collect2: ld returned 1 exit status
It appears that g++ isn't aware of the fact that I'm also trying to compile test2.cpp. Any ideas about what might be going on here?
Thanks,
--craig
Template classes must have their implementation visible to all translation units that use them, unless they are fully specialized.
That means you have to move the implementation in the header:
//test2.h
#ifndef __test2__
#define __test2__
class MyClass {
public:
template <class T>
MyClass(T &f_);
private:
int (*f)(int);
};
template <class T>
MyClass::MyClass(T &f_) {
f = f_;
}
#endif

Why getting linker error with vector?

I have for homework to write my own abstract class Vector. I make some of the code, but when I try to compile it I have error. This is the code:
vector.hh:
#ifndef VECTOR__HH__
#define VECTOR__HH_
template<class T> class Vector {
int capacity_;
int size_;
T* buffer_;
void ensure_capacity(unsigned size);
public:
Vector(int capacity=10)
: capacity_(capacity), size_(0), buffer_(new T[capacity])
{ }
~Vector() {
delete []buffer_;
}
int size() const {
return size_;
}
bool empty() const {
return size_ == 0;
}
T& operator[](int n) {
return buffer_[n];
}
const T& operator[](int n) const {
return buffer_[n];
}
void clear() {
// TODO
}
int capacity() const {
return capacity_;
}
T& front() {
return buffer_[0];
}
const T& front() const {
return buffer_[0];
}
T& back() {
return buffer_[size_-1];
}
const T& back() const {
return buffer_[size_-1];
}
void push_back(const T& value);
};
#endif
vector.cc:
#include "vector.hh"
template<class T>
void Vector<T>::ensure_capacity(unsigned size) {
if(capacity_>size+1) {
return;
}
capacity_ = capacity_ ==0?1:capacity_;
while(capacity_<size+1) {
capacity_*=2;
}
T* old_buffer = buffer_;
buffer_ = new T[capacity_];
memcpy(buffer_, old_buffer, sizeof(T)*size_);
delete [] old_buffer;
}
template<class T>
void Vector<T>::push_back(const T& value) {
ensure_capacity(size()+1);
buffer_[size_] = value;
size_++;
buffer_[size_] = '/0';
}
main.cc:
#include "vector.hh"
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
Vector<int> v(2);
v.push_back(10);
cout << v[0];
return 0;
}
And error is:
g++ -c -o main.o main.cc
g++ -Wall -g vector.o main.o -o hw02vector
main.o: In function 'main':
main.cc:(.text+0x37): undefined reference to 'Vector<int>::push_back(int const&)'
collect2: ld returned 1 exit status
make: * [hw02vector] Error 1
The linker error is coming because, for template classes the definition should always be visible. Either you can move all the content of vector.cc into vector.h. Or you can simply include vector.cc wherever you include vector.h.
side note:
Following lines in your .h file doesn't help:
#ifndef VECTOR__HH__
#define VECTOR__HH_
make both the macros similar such as, VECTOR__HH. This macros are used to avoid multiple inclusion of files.
In template programmming, the definition of the functions should be visible where the class template is defined. That is usually done by defining the functions inside the class itself.
So there are two ways you can solve your problem:
Move all the definitions from vector.cpp to vector.hh (which is in fact the usual solution). And delete Vector.cpp as its not needed.
Or, include the vector.cpp file at the end of vector.hh file, after the definition of Vector class template, like this:
#ifndef VECTOR__HH__
#define VECTOR__HH__ //<--- corrected this also!
template<class T>
class Vector {
//...
};
//...
#include "vector.cpp"
#endif VECTOR__HH__