I am realizing a templated Stack structure on the base of vector in C++. I am not sure what is wrong with my code.
Stack.h
#ifndef STACK_H_
#define STACK_H_
#include <vector>
using namespace std;
template <class T>
class Stack {
public:
Stack();
virtual ~Stack();
bool empty();
int size();
void push(T pushvar);
T pop();
private:
std::vector<T> container;
};
#endif /* STACK_H_ */
Stack.cpp
#include "Stack.h"
#include <vector>
//template <class T>
Stack::Stack()
:container(0)
{
}
Stack::~Stack() {
// TODO Auto-generated destructor stub
}
bool Stack::empty(){
return (container.empty());
}
Even before calling anything from the main, Eclipse gives me several errors. But I will give an exemplary main:
#include <iostream>
#include "Stack.cpp"
using namespace std;
int main() {
Stack<int> s;
cout << s.empty();
return (0);
}
The compiler returns the following errors:
Description Resource Path Location Type
'container' was not declared in this scope Stack.cpp /PracticeCpp/src line 23 C/C++ Problem
'template<class T> class Stack' used without template parameters Stack.cpp /PracticeCpp/src line 22 C/C++ Problem
invalid use of template-name 'Stack' without an argument list Stack.cpp /PracticeCpp/src line 12 C/C++ Problem
invalid use of template-name 'Stack' without an argument list Stack.cpp /PracticeCpp/src line 18 C/C++ Problem
Member declaration not found Stack.cpp /PracticeCpp/src line 12 Semantic Error
Member declaration not found Stack.cpp /PracticeCpp/src line 18 Semantic Error
Member declaration not found Stack.cpp /PracticeCpp/src line 22 Semantic Error
Method 'empty' could not be resolved Stack.cpp /PracticeCpp/src line 23 Semantic Error
Symbol 'container' could not be resolved Stack.cpp /PracticeCpp/src line 13 Semantic Error
I know that I haven't realized all the methods declared in the header file, but this is not my problem. Before I continue realizing them I want to understand where am I wrong?
Correction after the answers:
I followed the suggestions in the answers but still I don't get what continues to be wrong. I moved the template realizations to the header. I deleted the other unrealized methods to avoid confusion. Now my .cpp file is empty.
My new header file:
#ifndef STACK_H_
#define STACK_H_
#include <vector>
template <class T>
class Stack {
private:
std::vector<T> container;
public:
template <typename T>
Stack<T>::Stack() : container(0)
{
}
template <class T>
bool Stack::empty() {
return container.empty();
}
};
#endif /* STACK_H_ */
definition should be
template <typename T>
Stack<T>::Stack() : container(0)
{
}
And not in .cpp
The method Stack::empty() was never declared, you declared Stack<T>::empty(). The same is true for each other constructor, operator and method. Add a template declaration to each implementation to fix this error. Notice that the error message hints at the mistake by saying "invalid use of template-name 'Stack' without an argument list".
Example :
template<class T> bool Stack<T>::empty() {
return container.empty();
}
Implementations for template methods should be included in header files. See this question.
Edit :
Regarding your newest example, you've mixed up two solutions. Try either :
#include <vector>
template <class T>
class Stack {
private:
std::vector<T> container;
public:
Stack() : container(0)
{
}
bool empty() {
return container.empty();
}
};
OR
#include <vector>
template <class T>
class Stack {
private:
std::vector<T> container;
public:
Stack();
bool empty();
};
template<class T>
Stack<T>::Stack() : container(0)
{
}
template<class T>
bool Stack<T>::empty()
{
return container.empty();
}
In the first solution, you are defining your functions within the definition of your class. The compiler knows that you are working on class Stack<T>, you mustn't remind it. In the second solution, the functions are defined outside the class. Here, you must specify which class' empty method and constructor you are defining.
Related
Newbie to C++ so please forgive me. I'm trying to write a simple template class to implement the Stack data structure functionality. I've read through this question to understand how template declaration and implementation works: Why can templates only be implemented in the header file?. But I would like to use the solution where class declaration and implementation are separate (not defined inline in .h).
MyStack.h:
#include "StackNode.h"
#include "MyStack.tpp"
template <typename T>
class MyStack
{
private:
StackNode<T> *top;
public:
MyStack();
virtual ~MyStack();
};
MyStack.tpp:
#include "MyStack.h"
template <typename T>
MyStack<T>::MyStack()
: top(nullptr)
{
}
template <typename T>
MyStack<T>::~MyStack()
{
}
main.cpp:
#include "MyStack.h"
int main() {
MyStack<int> myStack;
return 0;
}
However compiling the above gives this error:
../src/MyStack.tpp:11:1: error: 'MyStack' does not name a type
../src/MyStack.tpp:18:1: error: 'MyStack' does not name a type
I know I'm missing something, but don't understand what. Thanks!
The problem is that you are including the .tpp file, which contains the class method definitions, before the class has actually been declared yet. You need to move that #include statement below the class declaration instead.
Also, the .tpp file should not be #include'ing the .h file that originally #include'd it. In fact, that won't work correctly since your .h file is missing header guards to prevent multiple inclusions within the same translation unit (ie, main.cpp in this case). So, you would end up with MyStack.h which includes MyStack.tpp which includes MyStack.h again, which causes an error when it tries to re-declare things that are already declared. Always declare a header guard in your .h files.
Try this instead:
MyStack.h:
#ifndef MyStack_H
#define MyStack_H
#include "StackNode.h"
template <typename T>
class MyStack
{
private:
StackNode<T> *top;
public:
MyStack();
virtual ~MyStack();
};
#include "MyStack.tpp"
#endif
MyStack.tpp:
template <typename T>
MyStack<T>::MyStack()
: top(nullptr)
{
}
template <typename T>
MyStack<T>::~MyStack()
{
}
I am trying to create a vector class that looks something like this:
template <typename T>
class Vector
{
.
.
.
};
#include "vector.cpp"
However, when I start writing my functions in "vector.cpp", CLion complains that I have duplicate functions. How do I work around this? I believe in NetBeans, I can add vector.h & vector.cpp to a folder called "Important Files" which would fix the problem. I am not sure what the equivalent in CLion is.
General Design of a template
example.h
#ifndef EXAMPLE_H
#define EXAMPLE_H
// Needed includes if any
// Prototypes or Class Declarations if any
template<class T> // or template<typename T>
class Example {
private:
T item_;
public:
explicit Example( T item );
~Example();
T getItem() const;
};
#include "Example.inl"
#endif // EXAMPLE_H
Example.inl
// Class Constructors & Member Function implementations
template<class T>
Example<T>::Example( T item ) : item_(item) {
}
template<class T>
Example<T>::~Example() {
}
template<class T>
T Example<T>::getItem() const {
return item_;
}
Example.cpp
#include "Example.h"
// Only need to have the include here unless if
// the class is non template or stand alone functions
// are non-template type. Then they would go here.
I'm currently doing an assignment for course and it involves creating a template class. I have the template class set up and everything, but I'm getting errors that I can't seem to fix. I have tried various solutions and neither have worked so far, I have also done a reasonable amount of research and found no answers, precisely relevant to my scenario, concerning the problem although many others have asked.
Here is the code thus far...
#ifndef STACK_H
#define STACK_H
#include "Queue.h"
#include "MyException.h"
#include <iostream>
using namespace std;
template<class T>
class Stack;
template<class T>
ostream& operator<<(ostream&,Stack<T>&);
template<class T>
class Stack
{
public:
Stack();
Stack(const Stack<T>& other);
void push(const T& el);
T pop();
T peek();
bool isEmpty();
friend ostream& operator<< <T>(ostream&,Stack<T>&);
Stack<T>& operator=(const Stack<T>& other);~Stack();
private:
class Node
{
public:
Node(const T& data, Node* n = 0)
{
element = data;
next = n;
}
T element;
Node* next;
};
Node* top;
};
#include "Stack.cpp"
#endif
that is the "Stack.h" and then there is
template<class T>
Stack<T>::Stack()
{
}
template <class T>
Stack<T>::Stack(const Stack<T>& other)
{
}
template <class T>
void Stack<T>::push(const T& el)
{
}
template <class T>
T Stack<T>::pop()
{
}
template <class T>
T Stack<T>::peek()
{
}
template <class T>
bool Stack<T>::isEmpty()
{
return false;
}
that is the "Stack.cpp".
I understand that the implementation being in a different file is not the generally accepted method, but unfortunately that is where the code needs to be. Now when I run this even without any real code, so to speak, i get the following errors.
3: expected constructor, destructor, or type conversion before '<' token
3: expected ';' before '<' token
9: expected constructor, destructor, or type conversion before '<' token
9: expected ';' before '<' token
17: expected init-declarator before '<' token
17: expected ';' before '<' token
23: expected init-declatator before '<' token
23: expected ';' before '<' token
and it goes on like that for each function up unto line 35.
Now, could it be my compiler? Could it be that I haven't finished all the functions and returned something yet?
Any help whatsoever would be largely appreciated, thanks.
Don't compile Stack.cpp in a separate translation unit; it is already included in Stack.h.
clang++ -c Stack.h -std=c++11
works just fine.
The problem is that you are suppose to include the .h file in your .cpp file. So remove the
#include "Stack.cpp"
That is at the bottom of your header file and add
#include "Stack.h"
to the top of your .cpp file.
What is wrong with this code:
Header:
#include <map>
using namespace std;
template<class T>
class ValueCollection
{
public:
ValueCollection(void);
int getValueCount(void);
map<string, T> Values;
};
Implementation:
#include "ValueCollection.h"
ValueCollection<class T>::ValueCollection(void)
{
}
int ValueCollection<class T>::getValueCount(void)
{
return Values.size();
}
Test:
#include "ValueCollection.h"
TEST(ValueCollection_TestCases, Default_Constructor_MapIsEmpty)
{
ValueCollection<int>* target = new ValueCollection<int>;
int expected = 0;
int actual = target->getValueCount();
ASSERT_EQ(expected, actual);
}
This is the error:
Error 1 error C2079: 'std::_Pair_base<_Ty1,_Ty2>::second' uses undefined class 'T' c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility 167 1 Refactor01
A couple of problems.
Your most immediate compiler error is caused by incorrect syntax in the implementation of the class template member functions. You must preface definition of a class template member with the template keyword. To wit:
template<class T> ValueCollection<T>::ValueCollection(void)
{
}
template<class T> int ValueCollection<T>::getValueCount(void)
{
return Values.size();
}
There's another problem too, which will only become apparent later as your program grows. You can't define template functions or classes in one Translation Unit and use them in antoher. The compiler must have the complete definition available in each translation unit.
Typically, the way this is accomplished is by defining template functions directly in the header file, right where they are declared. In your case:
template<class T>
class ValueCollection
{
public:
ValueCollection(void)
{
}
int getValueCount(void)
{
return Values.size();
}
map<string, T> Values;
};
That's just one way to accomplish this -- there are others. Another way is to use the so-called "inclusion method":
ValueCollection.h
template<class T>
class ValueCollection
{
public:
ValueCollection(void);
int getValueCount(void);
map<string, T> Values;
};
#include "ValueCollection.hpp:
ValueCollection.hpp
template<class T> ValueCollection<T>::ValueCollection(void)
{
}
template<class T> int ValueCollection<class T>::getValueCount(void)
{
return Values.size();
}
Yet another method would be to supply a new definition for each translation unit that wants to use the templates, but this would be highly unusual. (In fact, I have never done this in my 15 years of C++ programming)
implementation should read:
#include "ValueCollection.h"
template <class T>
ValueCollection<T>::ValueCollection(void)
{
}
template <class T>
int ValueCollection<T>::getValueCount(void)
{
return Values.size();
}
You require the template <class T> before every method in your implementation file too.
Okay, I'm trying to implement a templated class of an array-based queue called Queue.
Here's how I did it. First, is this the right way to implement a templated class?
The problem is, when I try to compile, I get the error messages
undefined reference to
'Queue::Queue()'
undefined reference to
'Queue::~Queue()'
Any ideas what's wrong? Am I declaring it wrong or implementing it wrong?
queue.h
#ifndef __QUEUE_H__
#define __QUEUE_H__
template <class T>
class Queue
{
int first;
T* array;
public:
Queue();
~Queue;
void enqueue(T next);
T dequeue();
bool is_empty();
bool is_full();
};
#endif
queue.cpp
#include "queue.h"
template <class T> Queue<T>::Queue(){
...
}
template <class T> Queue<T>::~Queue(){
...
}
template <class T> void Queue<T>::enqueue(T next){
...
}
template <class T> T Queue<T>::dequeue(){
...
}
template <class T> bool Queue<T>::is_empty(){
...
}
template <class T> bool Queue<T>::is_full(){
...
}
main.cpp
#include "queue.h"
#include <iostream>
using namespace std;
int main(){
Queue<int> test;
return 0;
}
Several issues:
The cause of your problem - C++ does not really support splitting templates into .h and .cpp files - you need to put everything in the header
The name __QUEUE_H__ is reserved for the C++ implementation, as are all names that contain double-underscores or begin with an underscore and an uppercase letter. You are not allowed to create such names in your own code.
You probably will find it more convenient to implement the queue in terms of a std::deque, rather than a C-style array
I assume you are doing this as a learning exercise, but if not you should know that the C++ Standard Library already contains a std::queue template class.
A template is really just a fancy form of macro that the compiler is aware of, for nearly every implementation of C++. The definitions have to be present so that the compiler can generate code in place of the template.