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.
Related
I'm receiving an error code when trying to declare a new stack object that uses a template class. I can't seem to find anything regarding this and most of the questions asked that I've found seem to refer to be for creating functions. Any help on how to resolve this would be greatly appreciated.
#include <stdio.h>
#include <iostream>
#include "stack4.h"
using namespace main_savitch_6B;
using namespace std;
int main(int argc, char **argv)
{
template <class Item> //error: expected expression
stack a;
a.push(4);
return 0;
}
my header file:
#ifndef MAIN_SAVITCH_STACK4_H
#define MAIN_SAVITCH_STACK4_H
#include <cstdlib> // Provides NULL and size_t
#include "node2.h" // Node template class from Figure 6.5 on page 308
namespace main_savitch_6B //7B
{
template <class Item>
class stack
{
public:
// TYPEDEFS
typedef std::size_t size_type;
typedef Item value_type;
// CONSTRUCTORS and DESTRUCTOR
stack( ) { top_ptr = NULL; }
stack(const stack& source);
~stack( ) { list_clear(top_ptr); }
// MODIFICATION MEMBER FUNCTIONS
void push(const Item& entry);
void pop( );
void operator =(const stack& source);
Item& top( );
void swap(stack& y);
// CONSTANT MEMBER FUNCTIONS
size_type size( ) const
{ return main_savitch_6B::list_length(top_ptr); }
bool empty( ) const { return (top_ptr == NULL); }
const Item& top( ) const;
private:
main_savitch_6B::node<Item> *top_ptr; // Points to top of stack
};
}
#include "stack4.template" // Include the implementation
#endif
stack<int> a;
if you want to define an instance of a template class
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.
driver.cc
#include <iostream>
#include "dynStack.h"
using namespace std;
// class definition
int main()
{
dynstack<double> it;
cout << "hello";
return 0;
}
dynStack.h
template <class T>
class dynstack {
public:
dynstack();
void push(T data);
private:
};
#include "dynStack.cc"
dynStack.cc
template <class T>
dynstack<T>::dynstack() { // <-- Here
}
template <class T> // // <-- And here
void dynstack<T>::push(T data)
{
}
I'm new to C++. The bolded lines are reported errors. The first one says "error: 'dynStack' does not name a type" The second one says "exrror: expected initializer before '<' token". I have spent hours on this and can't find the errors. Can anyone help? Thank you.
I was given a sample solution similar to this. Here is the sample:
main.cc
#include <iostream>
// #include the header file - as always
#include "temp.h"
using namespace std;
int main()
{
Thing<int> it(1);
Thing<double> dt(3.14);
cout << endl;
cout << "it = " << it.getData() << endl;
cout << endl;
cout << "dt = " << dt.getData() << endl;
cout << endl;
return 0;
}
temp.h
template <class T>
class Thing
{
private:
T data;
void setData(T data);
public:
Thing(T data);
T getData() const;
};
// MUST #include the implementation file here
#include "temp.cc"
temp.cc
// DO NOT #include the header file
template <class T>
Thing<T>::Thing(T data)
{
this->setData(data);
}
template <class T>
void Thing<T>::setData(T data)
{
this->data = data;
}
template <class T>
T Thing<T>::getData() const
{
return this->data;
}
It appears that you are trying to compile both driver.cc and dynStack.cc. The only file you compile with this setup is driver.cc.
Try this: Move contents of dynstack.cc entirely to dynstack.h and get rid of dynstack.cc
EDIT after reading comment responses:
If you want to keep dynstack.cc, its fine, just make sure you do not attempt to compile dynstack.cc I would name it a some other extension other than .cc which is conventionally for C++ implementation. Avoid .cc, .cpp, .cxx etc; use a uncommon extension such as .hc :-)
in "dualstk.h"
#ifndef __32_dualstk_h
#define __32_dualstk_h
#include <deque>
#include <cstdlib>
#include <iostream>
using namespace std;
enum stackNumber {One, Two};
template <class T>
class DualStack{
public:
DualStack() {count1 = 0; count2 = 0;};
//constructor. set counts to 0
void push(const T& item, stackNumber n);
void pop(stackNumber n);
T& top(stackNumber n);
const T& top(stackNumber n) const;
bool empty(stackNumber n) const;
int size(stackNumber n) const;
private:
deque<T> dualstackElements;
int count1, count2;
};
//error here
void DualStack::pop(stackNumber n){
}
#endif
Any idea why I'm pulling this error? What's strangest is that this is the book "Data Structures with C++ using STL" code and it states that this part is supposed to be correct as we are to simply implement the functions.
When I go to implement a most basic function, I get the error: "Expected a class or namespace."
DualStack is a template so you need to use template syntax on your function implementation.
template <class T>
void DualStack<T>::pop(stackNumber n){
}
create a separate file for your function implementation and include your header file
#include "dualstk.h"
void DualStack::pop(stackNumber n){
}
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