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
Related
To start off, I'm kind of new to instantiation files, headers, and source files.
I'm trying to get my code to compile, but I keep hitting a linker error where it says that I'm defining something twice.
I have 6 Files:
- Instantiation.cpp Lab5.cpp Students.cpp Queue.cpp Students.h Queue.h
Instantiation:
#include "Students.cpp"
#include "Lab5.cpp"
#include "Queue.cpp"
template class Queue<int>;
template class QueueNode<int>;
template class Queue < Students* >;
template class QueueNode < Students* >;
Lab5:
#include "Queue.h"
#include "Students.h"
#include <iostream>
using namespace std;
int main(){
Queue <Students*> studentQueue;
Queue <int> integerQueue;
return 0;
}
Students.cpp:
#include "Students.h"
Students::Students(){
}
void Students::printStudent(){
}
Queue.cpp:
#include "Queue.h"
template <class DataType>
Queue<DataType>::Queue(int i){
i = queueSize;
}
template <class DataType>
Queue<DataType>::~Queue(){
}
template <class DataType>
void Queue<DataType>::enQueue(const DataType){
}
template <class DataType>
DataType Queue<DataType>::deQueue(){
return 0;
}
template <class DataType>
DataType Queue<DataType>::topQueue() const {
return 0;
}
template <class DataType>
bool Queue<DataType>::isEmpty() const {
return true;
}
template <class DataType>
bool Queue<DataType>::isFull() const{
return true;
}
Students.h:
#ifndef STUDENTS_H
#define STUDENTS_H
class Students{
public:
char lastName[20];
char firstName[20];
int ID; // ID
Students(); // constr
void printStudent(); // print info
};
#endif
Queue.h:
#ifndef QUEUE_H
#define QUEUE_H
template <class DataType>
class QueueNode {
public:
DataType data;
QueueNode<DataType> *next;
};
template <class DataType>
class Queue {
private:
QueueNode<DataType> *front;
QueueNode<DataType> *back;
int queueSize; // size of a Queue
int queueCnt; // elem count in a Queue
public:
Queue(int = 10); // class constr. - initialize vars
~Queue(); // class destructor - remove all mem space used by queue elems
void enQueue(const DataType); // add item to back of queue
DataType deQueue(); // remove first item from queue and return its value
DataType topQueue() const; // return the value of the first item in the queue
bool isEmpty() const; // returns true if there are no elems in the queue
bool isFull() const; // returns true if no system mem for a new queue node
};
#endif
Here's the output:
http://i.imgur.com/cAPdtKG.png
Please, help.
I don't really get why it thinks I'm defining anything twice.
Any ideas on what is causing this compile-time error?
Basic setup:
main.cpp
#include <iostream>
#include "GroupTheorizer.h"
int main()
{
// ...
functs::Adder<char> A; // error on this line
/ ...
return 0;
}
GroupTheorizer.h
#ifndef __GroupTheory__GroupTheorizer__
#define __GroupTheory__GroupTheorizer__
class GroupTheorizer
{
// definitions of members of a GroupTheorizer object
// ...
};
#endif /* defined(__GroupTheory__GroupTheorizer__) */
GroupTheorizer.cpp
#include "GroupTheorizer.h"
#include <set>
#include <iostream>
#include <limits>
#include <string>
// ... implementations of GroupTheorizer members
// ...
namespace functs
{
class Adder
{
private:
static const char symbol = '+';
public:
T operator() (const T & x, const T & y) const { return x + y; };
char getSymbol(void) const { return symbol; };
};
// other functors ...
// ...
}
I'm fairly certain I linked the files together correctly, so what could be the problem?
Looking at your implementation of Adder, it seems like you mean it to be a template but haven't written it as such.
You're only missing the template <typename T> line.
template <typename T>
class Adder
{
private:
static const char symbol = '+';
public:
T operator() (const T & x, const T & y) const { return x + y; };
char getSymbol(void) const { return symbol; };
};
I'm using a stack class, however every time I push something to the stack, the executable freezes and stops working once the line of code pushing is reached.
Could I please get some help on as to why?
My stack.h:
#ifndef STACK_H
#define STACK_H
#include <cassert>
namespace standard
{
class Stack
{
public:
static const int CAPACITY = 30;
void stack() {used=0;};
void push (const char entry);
void pop();
bool empty() const;
int size() const;
char top() const;
private:
char data[CAPACITY];
int used;
};
}
#endif
My stack.cpp:
#include "stack.h"
namespace standard
{
void Stack::push(const char entry)
{
assert(size() < CAPACITY);
data[used] = entry;
++used;
}
void Stack::pop()
{
assert(!empty());
--used;
}
char Stack::top() const
{
assert(!empty());
return data[used-1];
}
int Stack::size() const
{
return used;
}
bool Stack::empty() const
{
if (size() == 0)
return true;
else
return false;
}
}
My calc.cpp:
#include "stack.h"
#include <iostream>
#include <fstream>
using namespace std;
using namespace standard;
void main()
{
Stack myStack;
ifstream input;
input.open("tests.txt");
if (input.fail())
{
cerr << "Could not open input file." << endl;
exit(0);
}
char i;
input >> i;
cout << i;
myStack.push(i); // This is where things go wrong.
cin.get();
}
Thanks for any help!
It looks like you are not initializing used, you have something that may look like a constructor here but it is not:
void stack() {used=0;};
this is what it should look like:
Stack() { used=0;};
So without a constructor used is going to be some indeterminate value and will probably end up with you attempting to access data way out of bounds. Also main should always return int.
void stack() {used=0;};
should this be capitalised? & remove the void!
Stack myStack;
should this be
Stack myStack = new Stack();
if you don't initialise it, the variable myStack will be a "null pointer".
I think you wrote this function wrong:
void stack() {used=0;};
//^^extra ; here
should be
Stack() {used = 0;}
//^^Note that constructor has no return type
You have never really used the stack member function which return void. This results in the fact that used was never initialized. You probably mean the constructor of Stack. Meanwhile, you should use constructor initialization list:
Stack(): used(0) {}
Hi im working on a program that uses an array of linked lists but im having trouble running it. I keep getting this error and I cannot find a way to fix it. Im only going to include parts of the code that way everything isnt too cluttered. The error message is saying that lines 112 in NodeADT.h, line 141 in MultiListADT.h and line 21 in main.cpp are the ones throwing the error. Ill highlight those lines to make it easier.
Main.cpp
#include <iostream>
#include "MultiListADT.h"
#include <fstream>
#include <string>
using namespace std;
void main(void)
{
MultiListADT<string,100> myList;
string item;
ifstream data;
string input;
int x=0;
data.open("input.txt");
while (!data.eof())
{
getline(data,input);
myList.AddToFront(input); //This is line 21
}
cout << myList << endl;
system("pause");
}
MultiListADT.h
#include <iostream>
#include <fstream>
#include "NodeADT.h"
#include <string>
using namespace std;
template <class TYPE,int threads>
class MultiListADT
{
public:
/** Constructor **/
MultiListADT();
/** Destructor **/
~MultiListADT();
/** Declare accessors (observers) **/
void ResetListForward(int=0);
void ResetListBackward(int=0);
bool IsEmpty(int=0);
int LengthIs(int=0);
bool Search(string, bool=true,int=0);
void GetNextItem(TYPE &,int i=0);
void GetPreviousItem(TYPE &,int=0);
int GetInfo(int=0);
friend ostream& operator << (ostream&, MultiListADT<TYPE, 100>&);
/** Declare mutators (transformers) **/
void MakeEmpty();
void AddToFront(TYPE);
void AddToRear(TYPE);
void InsertInOrder(TYPE);
void Delete(TYPE);
void Sort();
private:
NodeADT<TYPE,threads>* head[threads];
NodeADT<TYPE,threads>* tail[threads];
int length;
string indices[threads];
NodeADT<TYPE,threads>* currentNode[threads];
};
template <class TYPE,int threads>
MultiListADT<TYPE,threads>::MultiListADT()
{
head[threads] = new NodeADT<string,threads>();
tail[threads] = new NodeADT<string,threads>();
head[threads]->setNext(tail[threads]);
tail[threads]->setPrevious(head[threads]);
length = 0;
}
template <class TYPE,int threads>
void MultiListADT<TYPE,threads>::AddToFront(TYPE item)
{
head[0]->AddToFront(item); //This is line 141
length++;
}
NoteADT.h
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
const int null = 0;
template<class TYPE, int threads>
class MultiListADT;
template <class TYPE, int threads>
class NodeADT
{
public:
NodeADT();
NodeADT(TYPE);
~NodeADT();
TYPE getInfo();
NodeADT<TYPE, threads>* getPrevious(int=0);
NodeADT<TYPE, threads>* getNext(int=0);
void setNext(NodeADT<TYPE, threads>*,int=0);
void setPrevious(NodeADT<TYPE, threads>*,int=0);
bool Search(TYPE, bool=true,int=0);
void AddToFront(TYPE item);
void AddToRear(TYPE item);
void InsertInOrder(TYPE);
bool Delete(TYPE);
friend ostream& operator << (ostream&, MultiListADT<TYPE, threads>&);
private:
TYPE info;
NodeADT<TYPE, threads>* prev[threads];
NodeADT<TYPE, threads>* next[threads];
};
template <class TYPE,int threads>
NodeADT<TYPE,threads>::NodeADT()
{
prev[threads] = null;
next[threads] = null;
}
template <class TYPE,int threads>
NodeADT<TYPE,threads>::NodeADT(TYPE item)
{
info = item;
prev = null;
next = null;
}
template <class TYPE,int threads>
void NodeADT<TYPE,threads>::AddToFront(TYPE item)
{
NodeADT<TYPE,threads> *temp = new NodeADT<TYPE,threads>;
temp->info = item;
temp->prev[0] = this;
temp->next[0] = next[0];
next[0]->prev[0] = temp; //This is line 112
next[0] = temp;
}
What do YOU think the error means?
On line 112, where do the values for next, prev and temp come from and what are they set to when it crashes? Knowing the values, why do you think it crashed?
Also in one of your NodeADT constructors you assign null to the last element of the array. Or so it appears.
Question: What happens when you assign a value to the element numbered 100 in an array of 100 elements, when element counting starts at 0?
I think the answer, which Zan Lynx has implied, is that you are using threads as an index into your arrays in the constructor of MultiListADT. In AddToFront you use 0 as the index, but that element in the array has never been initialised.
I have truncated this post. The initial post is gone in order to facilitate reading. The relevant parts and problems are still there.
UPDATE
The error I was asked to post is:
[mehoggan#desktop qsort]$ g++ -o qsort -Wall main.cpp
/tmp/ccuAUzlh.o: In function `Sorters::QuickSorter<float>::test_and_sort(float*, int)':
main.cpp:(.text._ZN7Sorters11QuickSorterIfE13test_and_sortEPfi[Sorters::QuickSorter<float>::test_and_sort(float*, int)]+0x61): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& Sorters::operator<< <float>(std::basic_ostream<char, std::char_traits<char> >&, Sorters::Sorter<float>&)'
collect2: ld returned 1 exit status
[mehoggan#desktop qsort]$
and that is using the following code:
#ifndef SORTERS_H_
#define SORTERS_H_
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cmath>
#include <ctime>
#include <assert.h>
using std::vector;
using std::cin;
using std::cout;
using std::endl;
using std::ostream_iterator;
using std::istream_iterator;
using std::next_permutation;
using std::back_inserter;
using std::ostream;
namespace Sorters {
template<typename T>
class Sorter {
public:
Sorter( ) { };
virtual ~Sorter( ) { };
virtual void test_and_sort( T *data, int size )=0;
protected:
virtual void sort( typename vector<T>::iterator left, typename vector<T>::iterator right )=0;
vector<T> m_data;
};
template<typename T>
class QuickSorter : public Sorter<T> {
public:
QuickSorter( ) { };
virtual ~QuickSorter( ) { };
virtual void test_and_sort( T *data, int size );
private:
virtual void sort( typename std::vector<T>::iterator left, typename std::vector<T>::iterator right );
template<typename S> friend ostream& operator<< ( ostream &stream, Sorter<S> &sorter );
};
}
template<typename T>
void Sorters::QuickSorter<T>::sort( typename vector<T>::iterator left, typename vector<T>::iterator right ) {
}
template<typename T>
void Sorters::QuickSorter<T>::test_and_sort( T *data, int size ) {
for( int i=0;i<size;i++ ) {
vector<T> perm( &data[0], &data[i+1] );
do {
cout << (*this) << endl;
copy( perm.begin( ),perm.end( ),back_inserter( m_data ) );
this->sort( m_data.begin( ), m_data.end( ) );
} while( next_permutation( perm.begin( ), perm.end( ) ) );
m_data.clear( );
}
}
template<typename S> ostream& operator<< ( ostream &stream, Sorters::Sorter<S> &sorter ) {
copy( sorter->m_data.begin( ),sorter->m_data.end( ), ostream_iterator<S>( stream," " ) );
return stream;
}
#endif
UPDATE
I have written a smaller example so I know my concept works, it just get obfuscated when I use polymorphism and friend functions.
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
class Sample {
public:
Sample( ) { };
Sample( float *data, int size ) {
copy(&data[0],&data[size],back_inserter( m_data ) );
};
~Sample( ) { };
private:
vector<float> m_data;
friend ostream& operator<< ( ostream &stream, Sample &s ) {
copy( s.m_data.begin( ), s.m_data.end( ), ostream_iterator<float>( stream, " " ) );
return stream;
}
};
int main( int argc, char *argv[] ) {
float data[ ] = {1,2,3,4,5};
Sample s(data,5);
cout << s;
}
SOLUTION
Now to write the actual algorithm. I noticed though if I move m_data up to the parrent class I get compiler errors saying that m_data cannot be found. I guess that just means Insertion Sort, Radix Sort, Stooge Sort, ... will all have there own container.
#ifndef SORTERS_H_
#define SORTERS_H_
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cmath>
#include <ctime>
#include <assert.h>
using std::vector;
using std::cin;
using std::cout;
using std::endl;
using std::ostream_iterator;
using std::istream_iterator;
using std::next_permutation;
using std::back_inserter;
using std::ostream;
namespace Sorters {
template<typename T>
class Sorter {
public:
Sorter( ) { };
virtual ~Sorter( ) { };
virtual void test_and_sort( T *data, int size )=0;
protected:
virtual void sort( typename vector<T>::iterator left, typename vector<T>::iterator right )=0;
};
template<typename T>
class QuickSorter : public Sorter<T> {
public:
QuickSorter( ) { };
virtual ~QuickSorter( ) { };
virtual void test_and_sort( T *data, int size );
private:
vector<T> m_data;
virtual void sort( typename std::vector<T>::iterator left, typename std::vector<T>::iterator right );
friend ostream& operator<< ( ostream &stream, const QuickSorter &sorter ) {
copy( sorter.m_data.begin( ),sorter.m_data.end( ),ostream_iterator<T>( stream," " ) );
return stream;
}
};
}
template<typename T>
void Sorters::QuickSorter<T>::sort( typename vector<T>::iterator left, typename vector<T>::iterator right ) {
}
template<typename T>
void Sorters::QuickSorter<T>::test_and_sort( T *data, int size ) {
for( int i=0;i<size;i++ ) {
vector<T> perm( &data[0], &data[i+1] );
do {
copy( perm.begin( ),perm.end( ),back_inserter( m_data ) );
cout << (*this) << endl;
this->sort( m_data.begin( ), m_data.end( ) );
m_data.clear( );
} while( next_permutation( perm.begin( ), perm.end( ) ) );
}
}
#endif
First thing that you are printing the address by printing this. You need to print as,
cout << *this << endl;
In the comments you mentioned that you get errors. That's because of following line in operator << ():
vector<S> copy = sorter.m_data; // <--- where is 'm_data' ??
sorter is of type class Sorter<S> and there is no m_data inside it.
To fix this, either move m_data from QuickSorter to Sorter or overload operator << with QuickSorter<S>&.
You’re defining the operator << overload outside the Sorters namespace. That’s an error: you need to define it in the same namespace as the class (first of all, this is where you’ve declared it using the friend declaration; and second of all, this is where argument-dependent loopup is looking for the overload when you use it later on).
Why the code as shown acts the way it does is explained in the comments: cout << this prints a pointer, which results in an address being output. Your operator << overload expects a reference to an object, not a pointer, so it does not get used. As you said, the solution to this is to use cout << *this.
When I make that change, I ended up with a linker error. Somewhere between the templates, and the namespaces, something got confused, and I'm not clear on what. So I did the easy solution: define the function within the class.
Instead of
template<typename T>
struct QuickSorter {
template<typename T> friend ostream& operator <<(ostream&, QuickSorter<T>&);
}
template<typename T>
ostream& operator <<(ostream&, QuickSorter<T>&) { }
I did
template<typename T>
struct QuickSorter {
friend ostream& operator <<(ostream&, QuickSorter&) { }
};
Now, you don't have to worry about getting template parameters right and whatnot. Templated functions have to be declared inline anyhow, so you might as well just do this and get it over with. Note that you also do not declare operator << as a template itself... you are only interested in giving friendship to the one overload, for the specific T the class happens to be using.
Then, you get informed that the function accesses a member m_data, which does not exist in Sorter<T>. This is straight forward: Sorter<T> does not have that member; QuickSorter<T> does. So change the second parameter to the function to QuickSorter<T>& so that the compiler can find that particular member. This change is also reflected above.
The last thing I would do is make the operator overload accept a const QuickSorter<T>& instead of a non-const one. It does not modify the object in any way, so there is no reason not to.