Throwing and Catching exceptions with a template class - c++

What I'm trying to create is a TestScore Template class that just simply calculates the average of a array. I'm trying to throw a exception when a grade is negative or bigger than 100. I have created a NegativeScore exception class and a TooLargeScore exception class,both which just return a string message. In main, i create my array and ask the user for the grades, then use the class to get the average but for some reason it doesnt find the average. It doesnt print out the average when i try to. Im thinking the problem lies with my pointers but i dont know what the exact problem is, anyone know?
#ifndef TESTSCORES_H_INCLUDED
#define TESTSCORES_H_INCLUDED
#include <iostream>
#include "NegativeScore.h"
#include "TooLargeScore.h"
#include <iomanip>
using namespace std;
template <class T>
class TestScores
{
private:
T* testscores[];
public:
TestScores(T testscores[]);
T GetAverage();
};
template <class T>
TestScores<T>::TestScores(T testscores[])
{
*(this->testscores) = testscores;
}
template <class T>
T TestScores<T>::GetAverage()
{
T average;
T sum;
T counter;
for(int i = 0; i <= 5; i++)
{
if(*testscores[i] < 0)
{
throw NegativeScore("Test Score is negative, its invalid!");
}
else if(*testscores[i] > 100)
{
throw TooLargeScore("Test score it too high, its invalid!");
}
else
{
sum = sum + *testscores[i];
}
counter++;
}
average = sum / 5;
return average;
}
MAIN
int main()
{
int MAX = 5;
double scores[MAX];
for(int i = 0; i < MAX; i++)
{
int score;
cout << "Enter the test score for test "<< (i+1) << endl;
cin >> score;
scores[i] = score;
}
try
{
TestScores<double> tests(scores);
tests.GetAverage();
cout << tests.GetAverage() << endl;
}
catch(NegativeScore ex)
{
cout << ex.getMessage() << endl;
}
catch(TooLargeScore ex2)
{
cout << ex2.getMessage() << endl;
}
return 0;
}

Your problem is that you class holds an array of pointer to T, but you attempt to initialize it with a array of double (i.e. array of T values).
template <class T>
class TestScores
{
private:
T* testscores[];
public:
TestScores(T testscores[]);
T GetAverage();
};
template <class T>
TestScores<T>::TestScores(T testscores[])
{
*(this->testscores) = testscores; // <--- This is not doing what you think it is.
}
I am surprised that compiled, and you should strongly consider using a better compiler that will warn you of dubious operations.
You should change the class to hold a plain pointer-to-T, i.e. a T* testscores;, or better, an std::vector<T>.
For example, I could get your code working with this change:
template <class T>
class TestScores
{
private:
T* testscores; // Note simpler pointer to first element of array of length of 5.
public:
TestScores(T testscores[]);
T GetAverage();
};
You also have an error in the limits of your for loop in GetAverage (should not include 5), and your variables in that function are uninitialized and may hold garbage values.

Related

C++ program to simulate FIFO with class templates, returns value 3221225477 when dequeuing

I'm currently studying my second course of C++ object oriented programming at university, so I'll probably have bad programming practices and general errors in my code, so, please, point them out if you see any. I'm always open to learn.
I currently have an assignment on C++ templates, where I have to create a program with a class that simulates FIFO(First in First out) queue using a different class as the template type (Queue< Human >HumanQueue).
Queue.h
#ifndef QUEUE_H
#define QUEUE_H
#include "human.h"
template<class T>
class Queue : public Human{
public:
Queue(int = 5);
~Queue();
void enqueue(T);
T dequeue();
void PrintQueue();
private:
T* array;
int size, index;
};
#endif
Queue.cpp
#include <iostream>
#include "queue.h"
using namespace std;
template<class T>
Queue<T>::Queue(int s){
array = new T[s];
size = s;
index = 0;
}
template<class T>
Queue<T>::~Queue(){
delete [] array;
}
// Add object to end of array
template<class T>
void Queue<T>::enqueue(T obj){
if(index == size){
cout << "Rinda ir pilna, nevar pievienot elementu!" << endl; // Array full, can't add any more objects
return;}
else{
array[index] = obj;
index++;}
}
// Remove object from start of array and shift the whole array by 1 position
template<class T>
T Queue<T>::dequeue(){
for(int i = 0; i < size; i++){
array[i] = array[i + 1];
}
index--;
}
template<class T>
void Queue<T>::PrintQueue(){
for(int i = 0; i < index; i++){
cout << i + 1 << ". ";
array[i].PrintHuman();
}
}
main.cpp
#include <iostream>
#include "human.h"
#include "queue.h"
#include "queue.cpp"
using namespace std;
int main(){
Queue<Human> HumanQueue(3);
Human a("Janis", 1.86, 76);
Human b("Peteris", 1.76, 69);
Human c("Arturs", 1.79, 75);
Human d("Aleksis", 1.81, 78);
cout << "Elementu rinda" << endl; // Element queue
HumanQueue.enqueue(a);
HumanQueue.enqueue(b);
HumanQueue.PrintQueue();
cout << "\n//Pievienojam elementu rindai//" << endl; // Add element to queue
HumanQueue.enqueue(c);
HumanQueue.PrintQueue();
cout << "\n//Meginam pievienot vel 1 elementu rindai//" << endl; // Trying to add one more element to queue, should return, that queue is full
HumanQueue.enqueue(d);
HumanQueue.PrintQueue();
cout << "\n//Iznemam 2 elementus no rindas//" << endl; // Dequeue 2 elements from queue
HumanQueue.dequeue();
HumanQueue.dequeue();
HumanQueue.PrintQueue();
system("pause");
return 0;
}
The class "Human" is open to interpretation with any variables and functions of my choosing so I'm not including it in this thread.
The constructor, enqueue and print work fine, but when trying to dequeue I get a return value of 3221225477. From what I have gathered, it means it's some kind of problem with the way the program is using the memory. I used this same template for a previous project, where the types were int, char, float and it worked fine, but it doesn't like to work with objects.
Your dequeue function does not return a value.
It should be like this:
template<class T>
T Queue<T>::dequeue(){
if (index == 0) {
throw std::logic_error("queue is empty");
}
T value = array[0];
for(int i = 0; i < size - 1; i++){
array[i] = array[i + 1];
}
index--;
return value;
}
The exception is just an example of handling an empty queue when calling dequeue.

ERROR: What does "use of class template 's_array' requires template arguments" mean?

Im currently studying for an exam in c++.
I'm doing some practice questions on templates and have became totally stuck, i'v checked my code and it follows the solutions but this error keeps poping up. I'm unsure how I am passing in the wrong arguements (this is what I believe the issue is.
Code is listed below, any help is greatly appreciated
Tester
int main(){
s_array array(10);
array[5] = 5; //inbound access
cout << array[5] << endl;
array[-1] = 2;
cout << array[15];
return 0;
}
header, class and templates:
template <typename T>
class s_array {
public:
s_array(int size);
~s_array();
T &operator[](int i);
private:
int size;
T* data;
};
template <typename T>
s_array<T>::s_array(int size) : size(size)
{
/*
* If the size of the array is greater than zero
* A new array is created at the value of size
*/
if(size > 0) data = new T[size];
else{
std::cout << "Invalid array" << endl;
exit(1);
}
}
template <typename T>
s_array<T>::~s_array()
{
delete [] data;
}
/*
* Safety feature for the array going out of bounds
*/
template <typename T>
T& s_array<T>::operator[](int i)
{
if(i < 0 || i >= size){
std::cout << "index" << i << "is out of bounds" << endl;
exit(1);
}
return data[i];
}
You need to say what type the s_array is holding, for example this would define the array to contain int types. In the template definition, int will now be substituted everywhere that T used to be
s_array<int> array(10);

Template T Class Array

I have a (what should be simple) assignment in my C++ class.
Here is the assignment:
Create a class template that contains two private data members: T * array and int size. The class uses a constructor to allocate the array based on the size entered. There is member function that allows the user to fill in the array based on the size. In addition, there is a member function that sorts the array and displays the sorted elements. Use the destructor to delete the array. Develop the main( ) to create two objects to call member functions. As a result, the first object will hold its array of double type, and the other will hold its array of the int type.
Here is what I have came up with but coming up with an error of "Allocation of incomplete type 'T'":
#include <iostream>
#include <new>
#include <vector>
using namespace std;
template <class T>
class DynArray {
protected:
int size;
T ** DynamicArray = new T[size];
public:
DynArray(){
void CreateArray(){
cout << "Enter size of Array: ";
cin >> size;
for (int i = 0; i < size; ++i){
DynamicArray[i] = new T();
}
for (int i = 0; i<size; i++) {
cout << "Element " << i << ": ";
cin >> DynamicArray[i];}
}
//Sort Array
void Sort(T a[], int size)
{
int idx, pass;
for (pass=0; pass<size; ++pass){
for (idx=0; idx<size-1; ++idx){
if (a[idx] > a[idx+1])
swap(a[idx], a[idx+1]);}
}
for (int i=0; i<size; ++i) {
for (idx = 0; idx<size-1; ++idx) {
cout << a[idx] << " ";
}
}
}
void DeleteArray(){
for (int i = 0; i < size; ++i){
delete DynamicArray[i];
}
delete[] DynamicArray;
}
};
int main() {
DynArray<class T>();
return 0;
}
Not sure if I am a complete retard in my line of thinking or if I am just missing a small element. Any help is great.
Thank you #jblixr and #user3655463 for your help. I got it worked out I think after your hints and help.
Here is what I came up with for reference if anyone else is working on this.
#include <iostream>
#include <new>
#include <algorithm>
using namespace std;
//Template Class T
template <class T>
class DynArray {
protected:
int size;
T * DynamicArray;
public:
DynArray(){};
DynArray(size_t s): size(s) {
DynamicArray = new T[size];
for (int i = 0; i<size; i++) {
cout << "Element " << i << ": ";
cin >> DynamicArray[i];
}
}
//Sort Array
void Sort(){
sort(DynamicArray, DynamicArray+size);
for (int i=0; i<size; i++) {
cout << DynamicArray[i] << endl;
}
}
//Clear Heap
~DynArray() {
delete []DynamicArray;
}
};
int main() {
int sizeOfArry;
cout << "Enter size of Array: ";
cin >> sizeOfArry;
//Use as an int Array;
DynArray<int> intArray = DynArray<int>(sizeOfArry);
intArray.Sort();
}
From description you have provided looks to me you want to do sth like that:
#include <iostream>
#include <algorithm>
using namespace std;
template <class T>
class DynArray {
protected:
int size;
T * DynamicArray;
public:
DynArray(size_t s): size(s) {
DynamicArray = new T[s];
}
void CreateArray(){
size_t size;
cout << "Enter size of Array: ";
cin >> size;
if(size > this->size)
size = this->size;
for (int i = 0; i<size; i++) {
cout << "Element " << i << ": ";
cin >> DynamicArray[i];
}
}
//Sort Array
void Sort()
{
std::sort(DynamicArray, DynamicArray+size);
}
DynArray() {
delete []DynamicArray;
}
};
int main() {
DynArray<double> dob(3);
DynArray<int> di(3);
dob.CreateArray();
di.CreateArray();
dob.Sort(); di.Sort();
}
I am wondering that whether you are creating a one dimensional array or 2D array, your initial requirements states one dimensional array but you are using 2D array in your code. Anyway, I play along with one dimensional array.
error: allocation of incomplete type 'T'
T *DynamicArray = new T[size];
What you are trying to do here is in-class initialization which can be done for static data members and it is an c++11 extension for non-static data member. So I suggest you not to do so since you are learning. You can only declare the members and don't initialize here.
Even if you make static it cannot be allocated because the template type T is known only after object creation, So the compiler isn't aware of the type it is going to allocate during the compile time.
So it should be simply as
T *DynamicArray;
Nested functions
C++ doesn't support nested functions, learn C++ syntax.
Usage of constructors and destructors
A constructor will do the functionality of CreateArray() and the destructor will do the functionlaity of DeleteArray()
Instantiating a template class
You should explicitly mention the type within the angle brackets that the template class is going to use
DynArray<int> intArray; // if you want to use int
DynArray<float> floatArray;
You can also use your own custom class for type T, hope you will learn soon in your class.
DynArray<MyCustomClass> customArray;
If you correct all these things then your final skeleton will be like the below one
template <class T>
class DynArray {
protected:
int size;
T *DynamicArray ;
public:
DynArray() {
// initailize DynamicArray here
// use your CreateArray() code here
}
void sort() {
// your own sort logic
// No need to pass the size to this function, its a member function
}
~DynArray() {
// use your DeleteArray() code here
}
};
int main() {
DynArray<int> intArray;
intArray.sort()
return 0;
}
Simple, isn't it? :)

bubbleSort vector template class

I am working on an assignment where I need to sort vectors using a template so I can pass different data types to my class and sort them not using std::sort. so I am very stuck so far,
I don't really get how to use the template to accept my input from main().
PS. this is for Homework, that is why i am not using arrays and the sort function.
Here is my code so far.
using namespace std;
template <class T>
class SortableVector
{
private:
T a =0;
public:
SortableVector(); // constructor
~SortableVector(); // destructor
void bubble_sort(vector<T>, a)
{
for (int i = a.size(); i > 0;i--)
{
for (int j = 0, k = 1; k < i;j++, k++)
{
if (a[j] > a[k])
{
int swap = a[j];
a[j] = a[k];
a[k] = swap;
}
}
}
}
};
And my main is looking like this:
int main()
{
int alen, val;
vector<int> a;
cout << "Enter the number of elements : ";
cin >> alen;
for(int i = 0; i < alen; i++)
{
cin >> val;
a.push_back(val);
}
SortableVector::bubble_sort(a);
cout << "List of sorted elements: " << endl;
for(int i = 0; i < alen; i++)
{
cout << a[i] << " ";
}
cout << endl;
}
Any help will be welcome :)
Ok...
So I made some changes thanks to Namfuak
now I have a totally different problem
command line output;
Hw8_3.cpp:(.text+0x11): undefined reference to SortableVector<int>::SortableVector()'
Hw8_3.cpp:(.text+0x138): undefined reference toSortableVector::~SortableVector()'
Hw8_3.cpp:(.text+0x170): undefined reference to `SortableVector::~SortableVector()'
collect2: error: ld returned 1 exit status
I am really not getting this one. This is the code I have so far;
template <class T>
class SortableVector
{
private:
vector<T> vec;
public:
SortableVector(); // constructor
~SortableVector(); // destructor
void push_back(T push) {vec.push_back(push);}
T bubble_sort(vector<T> a);
};
template <class T>
T SortableVector<T>::bubble_sort(vector<T> a)
{
for (int i = a.size(); i > 0;i--)
{
for (int j = 0, k = 1; k < i;j++, k++)
{
if (a[j] > a[k])
{
T swap = vec[j];
vec[j] = vec[k];
vec[k] = swap;
}
}
}return 0;
}
And my main() ;
{
SortableVector<int> L;
int alen, val;
vector<int> a;
cout << "Enter the number of elements : ";
cin >> alen;
for(int i = 0; i < alen; i++)
{
cin >> val;
L.push_back(val);
}
L.SortableVector<int>::bubble_sort(a);
cout << "List of sorted elements: " << endl;
for(int i = 0; i < alen; i++)
{
cout << a[i] << " ";
}
}
Any other Idea? I am really lost here...
If you are using a template, your swap variable needs to be of that template type. IE:
T swap = a[j];
EDIT: Looking through, I don't think you are using the correct design. Your SortableVector should probably have a vector<T> as a member, IE:
template <class T>
class SortableVector
{
private:
std::vector<T> vec;
public:
SortableVector();
~SortableVector();
void push_back(T push) {vec.push_back(push);}
void bubble_sort() //You could also return a sorted version of vec
}
Otherwise, there is no reason for a SortableVector class, you can just take the function and put it in the global space as a templated function.
You need to provide definitions for the constructor and destructor.
If you don't declare them, the compiler will automatically create them for you. The constructor will call the default constructor on each element (and the base class if there is one) and the destructor will call the destructor of each class element.
However, since you have declared them, you also need to provide definitions.
The error is pretty clear:
Hw8_3.cpp:(.text+0x11): undefined reference to SortableVector<int>::SortableVector()'
Hw8_3.cpp:(.text+0x138): undefined reference toSortableVector::~SortableVector()' Hw8_3.cpp:(.text+0x170): undefined reference to `SortableVector::~SortableVector()' collect2: error: ld returned 1 exit status
You're not defining the constructor and the destructor...
SortableVector() { }
~SortableVector() { }
Or if you want:
template<class T>
SortableVector::SortableVector()
{
...
}
template<class T>
SortableVector::~SortableVector()
{
...
}
Also, this line L.SortableVector<int>::bubble_sort(a); why not just L.buble_sort(a);
Also, here:
template <class T>
T SortableVector<T>::bubble_sort(vector<T> a)
Did you know you're passing a copy of a instead of a reference? This means you any modifications to that vector will not be live in vector<int> a; in your main function or whatever function you're calling it from:
template <class T>
T SortableVector<T>::bubble_sort(vector<T>& a)
Notice the &
This:
vec[j] = vec[k];
vec[k] = swap;
Did you mean a?
This class member is useless:
vector<T> vec;
I'd suggest providing functions for appending to that member instead and remove the vector<T>& a parameter from the bubble_sort function in the class, then instead of making another vector in your main or w/e, use push on your SortableVector class instance.
#include <vector>
#include <algorithm> //This library give us some handy function swap
#include <iostream>
#include <random>
// This is a function to create random number between 1 and 10
static int random_int(){
static std::random_device rd;
static std::mt19937 prng{ rd() };
static std::uniform_int_distribution<> d10{1, 10};
return d10(prng);
}
template<class T>
class SortableVector{
//By default element define in classes are private so no need to specify
std::vector<T> v_;
public:
//You dont need to specify constructor
//Also, you dont need to specify destructor.
//This is because the default constructor and destructor are ok.
//The default constructor use item to item copy. In this case it's gonna copy the vector val_ wich is ok.
//For the destructor, we don't need to do anything
//Usually you use const T& to avoid copy
void push_back(const T& val){
v_.push_back(val);
}
//Here i don't really know what u want to do.
//Do you want to sort your inner vector and return it ?
//Or do you want to make a copy and return it ?
//Let's make a static method so it helps us covering both cases.
//This method is static so it can be used outside of an instance.
//It's like a function that is define inside the scope of this class.
static void bubble_sort(std::vector<T>& v){
//Using the correct type is always better.
//In this case it's the type that define the size of this particular vector is :
size_t size = v.size();//Or with c++11 : auto size = v.size()
bool change;
do{
change = false;
for(int i = 0; i < size - 1; ++i){
if(v[i-1] > v[i]){
std::swap(v[i-1],v[i]);
change = true;
}
}
}
while(change);
}
//This is the method version using the static one.
std::vector<T>& bubble_sort(){
bubble_sort(v_);
return v_;
}
};
int main() {
SortableVector<int> ss;
for(int k = 0; k < 10; ++k){
ss.push_back(random_int());
}
for(auto& elem : ss.bubble_sort()){//C++ 11 foreach
std::cout << elem << std::endl;
}
}

C++ template problem

I would like to implement a Base class with attributes of a size I already know at compile-time. So my idea was to use a template for this Base class. The following code compiles and runs fine under VC++9.0.
Class definition in the .h file
template<int N> class BaseClass
{
int* idx;
int* incr;
int* limit;
public:
BaseClass(void);
~BaseClass(void);
void LoopMethod(void);
};
Implementation of the class methods in the .cpp file
#include "BaseClass.h"
#include<iostream>
using namespace std;
// instantiation
template class BaseClass<2>;
template<int N> BaseClass<N>::BaseClass(void)
{
idx = new int [N];
incr= new int [N];
limit = new int[N];
for(int m = 0; m < N; m++)
{
idx[m] = 0;
incr[m] = 1;
limit[m] = 2;
}
}
template<int N> BaseClass<N>::~BaseClass(void)
{
}
template<int N> void BaseClass<N>::LoopMethod( )
{
for( idx[N-1]; idx[N-1] < limit[N-1]; idx[N-1] += incr[N-1] )
{
cout << "LoopMethod Nr " << N-1 << " is called." << endl;
}
}
Implementation of the main-function:
#include<cstdlib>
#include "BaseClass.h"
using namespace std;
int main()
{
BaseClass<2> baseObj;
baseObj.LoopMethod();
system("PAUSE");
return 0;
}
Now I want to nest the for-loops from the LoopMethod times the size of the class attributes. I.e. the compiler should generate a code I would write by Hand as
template<int N> void BaseClass<N>::LoopMethod( )
{
for( idx[0]; idx[0] < limit[0]; idx[0] += incr[0] )
{
for( idx[1]; idx[1] < limit[1]; idx[1] += incr[1] )
{
cout << "LoopMethod Nr " << 1 << " is called." << endl;
}
cout << "LoopMethod Nr " << 0 << " is called." << endl;
}
}
Anyway, I can prompt the compiler to do this, if I do not declare the BaseClass to be a template class. The code for this would then look like:
class BaseClass
{
int* idx;
int* incr;
int* limit;
public:
BaseClass(void);
~BaseClass(void);
template<int M> void LoopMethod(void);
};
Implementation of the class methods in the .cpp file
#include "BaseClass.h"
#include<iostream>
using namespace std;
template void BaseClass::LoopMethod<1>();
BaseClass::BaseClass(void)
{
idx = new int [2];
incr= new int [2];
limit = new int[2];
for(int m = 0; m < 2; m++)
{
idx[m] = 0;
incr[m] = 1;
limit[m] = 2;
}
}
BaseClass::~BaseClass(void)
{
}
template<int M> void BaseClass::LoopMethod( )
{
for( idx[M]; idx[M] < limit[M]; idx[M] += incr[M] )
{
cout << "LoopMethod Nr " << M-1 << " is called." << endl;
LoopMethod<M-1>();
}
}
template<> void BaseClass::LoopMethod<0>(void)
{
idx[0] = 0;
for( idx[0]; idx[0] < limit[0]; idx[0] += incr[0] )
{
// do something
cout << "Now the inner loop is executed" << endl;
}
}
Implementation of the main-function:
#include<cstdlib>
#include "BaseClass.h"
using namespace std;
int main()
{
BaseClass baseObj;
baseObj.LoopMethod<1>();
system("PAUSE");
return 0;
}
But the solution I am searching for is to have a template class with a template method “LoopMethod” owing its own template parameter which tells the compiler how many times to nest the for-Loop. I have tried various possibilities but without success. Does anybody have a suggestion or even know a solution for this template problem?
Thanks in advance for your help,
Markus.
There are a lot of issues with your template:
What exactly is the purpose of the whole thing?
Why are you initialising the pointers with new? You know the size at compile time so why not just make them arrays?
You are not deleting the memory you are allocating
Exception safety if new fails for one of the later arrays
Implementation probably should be in the header file unless it is used for very few values of N which you instantiate
Better to use classes that exist that do this kind of thing, eg boost::array
Refactor out various sections of it.
But the solution I am searching for is
to have a template class with a
template method “LoopMethod” owing its
own template parameter which tells the
compiler how many times to nest the
for-Loop
Is that what you are asking:
template<int N>
struct X
{
template<int M>
void loop();
};
template<int N>
template<int M>
void X<N>::loop<M>()
{
}