Error in converting class to template class - c++

Code is a little long because I can't really trace the source of the error, so I'm not sure how much more I can remove (still new to C++ templates)
Already omitted are member functions and methods that I've also converted to templates, I don't think they're relevant for the error.
Below was a given class that I've been converting to an abstract template class, when compiled, I get the following compile-time error:
1.cpp:116:3: error: no matching function for call to 'testPFArrayD'
testPFArrayD();
1.cpp:87:6: note: candidate template ignored: couldn't infer template
argument 'T' void testPFArrayD()
Line 166 is the Main() call for the function testPFArrayD(). The actual purpose of the class isn't very important in this case, I just need to know the issue in converting it to a template.
The full-length, original source code (not converted to a template) for the class is here
#include <iostream>
using namespace std;
template <typename T>
class PFArrayD
{
public:
PFArrayD();
PFArrayD(int capacityValue);
PFArrayD(const PFArrayD& pfaObject);
void addElement(T element);
bool full() const { return (capacity == used); }
int getCapacity() const { return capacity; }
int getNumberUsed() const { return used; }
void emptyArray() { used = 0; }
double& operator[](T index);
PFArrayD& operator =(const PFArrayD& rightSide);
~PFArrayD();
private:
double *a;
int capacity;
int used;
};
template <typename T>
PFArrayD<T>::PFArrayD() :capacity(50), used(0)
{
a = new T[capacity];
}
template <typename T>
void testPFArrayD()
{
int cap;
cout << "Enter capacity of this super array: ";
cin >> cap;
PFArrayD() temp (cap); //?????????????????
cout << "Enter up to " << cap << " nonnegative numbers. \n";
cout << "Place a negative number at the end. \n";
double next;
cin >> next;
while ((next >= 0) && (!temp.full()))
{
temp.addElement(next);
cin >> next;
}
cout << "You entered the following " << temp.getNumberUsed() << " numbers:\n";
int index;
int count = temp.getNumberUsed();
for (index = 0; index < count; index++)
cout << temp[index] << " ";
cout << endl;
cout << "(plus a sentinel value.)\n";
}
int main()
{
cout << "This program tests the class PFArrayD.\n";
char ans;
do {
testPFArrayD();
cout << "Test again? (y/n) ";
cin >> ans;
} while ((ans == 'y') || (ans == 'Y'));
//system("pause");
return 0;
}

Related

How do I create a template object based off of user input?

I have made an array based queue with a template so that the user can decide what kind of data is held inside the queue but I cannot figure out how gather input and then from that create a queue of that data type.
Here is my Queue
#include <memory>
using namespace std;
template<class itemType>
class Queue
{
private:
unique_ptr<itemType []> queueArray;
int queueSize;
int front;
int rear;
int numItems;
public:
Queue(int);
itemType peekFront();
void enqueue(itemType item);
void dequeue();
bool isEmpty() const;
bool isFull() const;
void clear();
};
And I have tried this and many other ways but cant figure out how to tell what type of data the user inputs and then create a Queue with that type of data.
int main()
{
const int MAXSIZE = 5;
int choice;
cout << "1. integer queue\n" << "2. string queue\n" << "3. float queue\n";
choice = menu();
if(choice == 1)
{
Queue<int> newQueue(MAXSIZE);
int data;
}
else if(choice == 2)
{
Queue<string> newQueue(MAXSIZE);
string data;
}
else if(choice == 3)
{
Queue<float> newQueue(MAXSIZE);
float data;
}
else
cout << "Number needs to be 1-3." << endl;
cout << "Enter an item to add" << endl;
cin >> data;
newQueue->enqueue(data);
Thanks everyone for the help! I almost have it done, but now that I have all virtual functions how do I call peekFront()? Since the virtual functions can't return itemType right?
You need runtime polymorphism to solve this problem. This can either be achieved with a base class:
class IQueue {
virtual ~IQueue() = default;
virtual void enqueue(istream&) = 0;
};
template<class itemType>
class Queue : public IQueue
{
//...
public:
void enqueue(istream& is) override {
itemType item;
is >> item;
enqueue(item);
}
//...
};
And use as a pointer
int main() {
//...
unique_ptr<IQueue> newQueue;
//...
if(choice == 1)
{
newQueue.reset(new Queue<int>(MAXSIZE));
int data;
}
//...
newQueue->enqueue(cin);
//...
}
Or something like std::variant.
Well, you are almost there.
You just need to not loose the scope of your data and newQueue variables.
template <typename T>
T input()
{
T data;
cout << "Enter an item to add" << endl;
cin >> data;
return data;
}
int main()
{
const int MAXSIZE = 5;
int choice;
cout << "1. integer queue\n" << "2. string queue\n" << "3. float queue\n";
choice = menu();
if(choice == 1)
{
Queue<int> newQueue(MAXSIZE);
newQueue->enqueue(input<int>());
}
else if(choice == 2)
{
Queue<string> newQueue(MAXSIZE);
newQueue->enqueue(input<string>());
}
else if(choice == 3)
{
Queue<float> newQueue(MAXSIZE);
newQueue->enqueue(input<float>());
}
else
cout << "Number needs to be 1-3." << endl;
}
You still have some problem with this architecture, for example, maybe you want to move your queues outside these ifs, otherwise you can't use them anymore. (Read about scope).
You could also look at std::variant for these kind of situations.

C++ SimpleVector Using Templates

I am trying to get my program to let the user choose which data type they would like to use, 1 for int, 2 for double, and 3 for string. Take that type and make it the type for our dynamic array. Allow the user to say how many inputs of the data they would like, and then allow the user to enter the data.
For some reason not clear to me, my program crashes right after the user enters any number for the type they want to use.
(I also have some other methods to implement, but I wanted to get this fixed first. So that's why there are unused methods.)
Is there something I am not seeing here? Any help is greatly appreciated. Thank you so much.
#include <iostream>
#include <cstdlib>
using namespace std;
template <class T>
class SimpleVector
{
private:
T *tempPointer;
int lengthOfArray;
public:
SimpleVector();
~SimpleVector();
SimpleVector(int lengthOfArray);
SimpleVector(const SimpleVector& copy);
int getArraySize();
T getElementAt(int n);
T & operator[](int index);
};
// default no-arg constructor
template <class T>
SimpleVector<T>::SimpleVector()
{
tempPointer = NULL;
lengthOfArray = 0;
}
// destructor for deallocating memory
template <class T>
SimpleVector<T>::~SimpleVector()
{
delete [] tempPointer;
}
// single argument constructor
template <class T>
SimpleVector<T>::SimpleVector(int dynamicArray)
{
lengthOfArray = dynamicArray;
tempPointer = new T[lengthOfArray];
}
// Copy constructor
template <class T>
SimpleVector<T>::SimpleVector(const SimpleVector& copy)
: lengthOfArray(copy.lengthOfArray), tempPointer(new int[copy.lengthOfArray])
{
int newSize = copy->size();
tempPointer = new T[newSize];
for(int i = 0; i < newSize; i++){
tempPointer[i] = copy.tempPointer[i];
}
}
// gets the size of the dynamic array
template <class T>
int SimpleVector<T>::getArraySize()
{
return lengthOfArray;
}
// returns element from array at specified position
template <class T>
T SimpleVector<T>::getElementAt(int n)
{
return *(tempPointer + n);
}
// returns reference to the element in array indexed by subscript
template <class T>
T & SimpleVector<T>::operator[](int index)
{
return this->tempPointer[index];
}
int main()
{
int dataType;
int dataSize = 0;
char keepGoing;
do{
cout << "What type of data do you want to enter?\n(1 for integer, 2 for double and 3 for strings)" << endl;
cin >> dataType;
cout << "How many data inputs? " << endl;
cin >> dataSize;
SimpleVector <int> list1(dataSize);
if (dataType == 1) {
SimpleVector <int> list1(dataSize);
}
else if (dataType == 2) {
SimpleVector <double> list1(dataSize);
}
else if (dataType == 3) {
SimpleVector <string> list1(dataSize);
}
else {
cout << " That's not an available option. Bye! " << endl;
return 0;
}
cout << "Please enter the data:" << endl;
for (int i = 0; i <= dataSize; i++) {
cin >> list1[i];
}
cout << "Do you want to enter data again? (y/n?)" << endl;
cin >> keepGoing;
}while((keepGoing == 'Y') | (keepGoing == 'y'));
return 0;
}
For some reason not clear to me, my program crashes right after the user enters any number for the type they want to use.
I would suggest, that you test your program multiple times, when you are writing it. As #Jarod42 said in his comment, your if statements don't really do much, because your
SimpleVector <type> list1(dataSize);
gets destroyed after { }.
So basically whatever number user types, your SimpleVector will always be of the type int.
Now when you try to:
cout << "Please enter the data:" << endl;
for (int i = 0; i <= dataSize; i++) {
cin >> list1[i];
}
you are calling function:
template <class T>
T & SimpleVector<T>::operator[](int index)
{
return this->tempPointer[index];
}
At this point, you pointer is pointing to NULL, but you are trying to access [index] of your pointer, which is pointing to NULL. That's why you program crashes.
EDIT:
I'm not sure if this is what you want, but i'll give it a try :
do{
cout << "What type of data do you want to enter?\n(1 for integer, 2 for double and 3 for strings)" << endl;
cin >> dataType;
cout << "How many data inputs? " << endl;
cin >> dataSize;
if (dataType == 1) {
SimpleVector <int> list1(dataSize);
cout << "Please enter the data:" << endl;
for (int i = 0; i <= dataSize; i++) {
cin >> list1[i];
}
}
else if (dataType == 2) {
SimpleVector <double> list1(dataSize);
cout << "Please enter the data:" << endl;
for (int i = 0; i <= dataSize; i++) {
cin >> list1[i];
}
}
else if (dataType == 3) {
SimpleVector <string> list1(dataSize);
cout << "Please enter the data:" << endl;
for (int i = 0; i <= dataSize; i++) {
cin >> list1[i];
}
}
else {
cout << " That's not an available option. Bye! " << endl;
return 0;
}
cout << "Do you want to enter data again? (y/n?)" << endl;
cin >> keepGoing;
}while((keepGoing == 'Y') | (keepGoing == 'y'));

Error "identifier not declared in this scope" - C++

C++ beginner here. So I have several functions in which I am trying to pass an element of array of pointers (which contains structures (records)). I'm having trouble doing this and I'm pretty stuck and frustrated. I'm very new to pointers and memory so go easy on me. I keep getting errors when I try to pass the specific structure element into the function. (BTW: The functions are declared in a header file)
What can I do to fix/change this and make it work? Thank you for the help, it is very much appreciated.
The error I get:
'changeAssignmentGradeForStudent' was not declared in this scope
Code:
Structure student:
typedef struct
{
char firstName[50];
char lastName[50];
char studentNumber[10];
char NSID[10];
float assignments[10];
float midterm;
float final;
} Student;
void useFunctions(int recordNum)
{
// array of 10 student references
Student *students[recordNum];
// values received from the user
for (int i = 0; i < recordNum; i++)
{
cout << "Student " << i + 1 << ": " << endl;
students[i] = readStudentRecordFromConsole();
}
cout << "Would you like to make any changes to any student records? (N or Y)" << endl;
cin >> answer;
if (answer == 'N')
{
return;
}
else
{
cout << "Which student?" << endl;
cin >> student;
students[student - 1] = gradeChanges(*students[student - 1], recordNum, student);
}
}
Student *gradeChanges(Student *s, int recordNum, int student)
{
Student *changedStudent = s;
int gradeChange, aNum;
cout << "assignment number to change?" << endl;
cin >> aNum;
cout << "assignment to change?" << endl;
cin >> gradeChange;
changeAssignmentGradeForStudent(changedStudent, aNum, gradeChange); // where the errors are
return changedStudent;
}
void changeAssignmentGradeForStudent(Student *s, int a, int g)
{
if (s != NULL)
{
s->assignments[a] += g;
}
}
PS: Sorry if my code is not formatted correctly. If it isn't, feel free to edit it, thank you.
The function changeAssignmentGradeForStudent was not declared or defined before it was used, so the compiler doesn't know about it yet. You can either move the function definition up before useFunctions() or declare it at the top of the file like this:
void changeAssignmentGradeForStudent(Student*, int, int);
The compiler needs to see a declaration of your functions before these are referred to. You have to put that declaration before you call a function like this:
// This is the (forward) declaration:
void changeAssignmentGradeForStudent(Student* s, int a, int g);
Student * gradeChanges(Student* s, int recordNum, int student) {
Student *changedStudent = s;
int gradeChange, aNum;
cout << "assignment number to change?" << endl;
cin >> aNum;
cout << "assignment to change?" << endl;
cin >> gradeChange;
changeAssignmentGradeForStudent(changedStudent, aNum, gradeChange); // where the errors are
return changedStudent;
}
// This is the definition:
void changeAssignmentGradeForStudent(Student* s, int a, int g) {
if (s != NULL) {
s->assignments[a] += g;
}
}

I have trouble with some pointers, access location failed at the end of debugging

// header.h
#include <iostream>
#include <list>
#include <fstream>
using namespace std;
class Biblioteca
{
public:
Biblioteca();
void closeFile();
bool chose();
ofstream Intrare;
ofstream Memorare;
};
class Publicatii:public virtual Biblioteca
{
public:
string retTitlu();
string retEditura();
string retAutor();
int retAn();
int retTiraj();
int retNumar();
int retFrecventa_de_aparitii();
protected:
string Titlu, Editura, Autor;
int An, Tiraj, Numar, Frecventa_de_aparitii;
};
class Carti: public Publicatii , public virtual Biblioteca
{
public:
void readBook();
Carti();
void insertMyBook();
void writeBookFile();
void inTitlu(Carti& a);
void inEditura(Carti& a);
void inAutor(Carti& a);
void inTiraj(Carti& a);
void inAn(Carti& a);
protected:
list<Carti*>books;
list<Carti*>::iterator i;
};
class Reviste: public Publicatii , public virtual Biblioteca
{
public:
void readMagazine();
Reviste();
void insertMyMagazine();
void writeMagazineFile();
protected:
list<Reviste*> magazine;
list<Reviste*>::iterator j;
};
The other cpp file of the header
#include<iostream>
#include<string>
#include"biblioteca.h"
#include <list>
#include<fstream>
//-----Biblioteca------
Biblioteca::Biblioteca()
{
Memorare.open("in.txt");
}
void Biblioteca::closeFile()
{
Memorare.close();
}
bool Biblioteca::chose()
{
int k;
cout << "Ce doriti sa introduceti?" << endl << endl;
cout << "1--Carte" << endl;
cout << "2--Biblioteca" << endl;
cin >> k;
switch (k)
{
case 1:
return true;
break;
case 2:
return false;
break;
}
}
//-------Publicatii------
string Publicatii::retTitlu()
{
return Titlu;
}
string Publicatii::retEditura()
{
return Editura;
}
string Publicatii::retAutor()
{
return Autor;
}
int Publicatii::retAn()
{
return An;
}
int Publicatii::retTiraj()
{
return Tiraj;
}
int Publicatii::retNumar()
{
return Numar;
}
int Publicatii::retFrecventa_de_aparitii()
{
return Frecventa_de_aparitii;
}
//---------Carti---------
void Carti::inTitlu(Carti& a)
{
Titlu = a.retTitlu();
}
void Carti::inEditura(Carti& a)
{
Editura = a.retEditura();
}
void Carti::inAutor(Carti& a)
{
Autor = a.retAutor();
}
void Carti::inTiraj(Carti& a)
{
Tiraj = a.retTiraj();
}
void Carti::inAn(Carti& a)
{
An = a.retAn();
}
void Carti::readBook()
{
cout << "\nO noua carte" << endl<<endl;
cout << "\nTitlu= ";
cin >> Titlu;
cout << "\nEditura= ";
cin >> Editura;
cout << "\nAn= ";
cin >> An;
cout << "\nTiraj= ";
cin >> Tiraj;
cout << "\nAutor= ";
cin >> Autor;
}
Carti::Carti()
{
books.resize(1);//one book
}
void Carti::insertMyBook()
{
Carti carti;
for (i = books.begin(); i != books.end(); i++)
{
carti.readBook();
(*i)->inTitlu(carti);
(*i)->inEditura(carti);
(*i)->inAn(carti);
(*i)->inTiraj(carti);
(*i)->inAutor(carti);
//books.insert(i, *i);
}
}
void Carti::writeBookFile()
{
Memorare << "---Carti---" << endl;
for (i = books.begin(); i != books.end(); i++)
Memorare << *i << " ";
}
//-------Reviste--------
void Reviste::readMagazine()
{
cout << "\nO noua revista" << endl<< endl;
cout << "\nTitlu= ";
cin >> Titlu;
cout << "\nEditura= ";
cin >> Editura;
cout << "\nAn= ";
cin >> An;
cout << "\nTiraj= ";
cin >> Tiraj;
cout << "\nNumar= ";
cin >> Numar;
cout << "\nFrecventa de aparitie= ";
cin >> Frecventa_de_aparitii;
}
Reviste::Reviste()
{
magazine.resize(1);//one magazine
}
void Reviste::insertMyMagazine()
{
Reviste reviste;
for (j = magazine.begin(); j != magazine.end(); j++)
{
reviste.readMagazine();
//some conde
magazine.insert(j, *j);
}
}
void Reviste::writeMagazineFile()
{
Memorare << "---Reviste---" << endl;
for (j = magazine.begin(); j != magazine.end(); j++)
cout << *j << " ";
}
Sorry for the code thone here, I'm new to Stackoverflow and I'm in a hurry, that's why I don't write "beautiful code". My problem is, when I want to just insert elements in my list
void Carti::insertMyBook()
{
Carti carti;
for (i = books.begin(); i != books.end(); i++)
{
carti.readBook();
(*i)->inTitlu(carti);
(*i)->inEditura(carti);
(*i)->inAn(carti);
(*i)->inTiraj(carti);
(*i)->inAutor(carti);
books.insert(i, *i);
}
}
it's working like a clockwork and after I compile I type some information from my keyboard and at the end I get a big error like "Acces Violation Reading 00000001C"
Why? I tried other metods like allocating dynamic memory with the new operator, I tried a lot of things but in the end I have like this error or type "example" doesn't match with "example".
Sorry for my bad English spelling, but in this program I just wanted to make a program that reads magazines and boooks and stored to a library named "biblioteca", and "carte" means books and " Reviste" means magazine... and I want it to be memorized in a list because I need to insert elements or delete what ever book or magazine I choose...and all the information I want to be saved in a file for instance "out.txt" or "in.txt"
The crash is because the iterator is NULL at line (*i)->inTitlu(carti);.
The issue is in method:
Carti::Carti()
{
books.resize(1);//one book
}
and books are:
list<Carti*>books;
What you are trying to is to resize the list of Carti's to 1 but as you have a list of pointers to Carti objects rather than Carti objects, resizing operation will not create a Carti object by calling it's constructor but a pointer.
Apart from that you have major issues with your design and coding, a Carti object storing a list of other pointers-to-Carti objects definitely is not a good idea. You may consider creating another 'holding' class to store a list of Carti's you have created.

push_back() not working for custom data type (template class)

Apparently push_back() is not working for my custom data class T. On compilation I get the following error:
error: no matching function for call to ‘Vector::push_back(int&)’
Could someone explain to me why that is? Thank you.
#include <std_lib_facilities>
#include <numeric>
#include <vector>
#include <string>
// vector<int> userin;
// int total;
// bool success;
class T
{
public:
void computeSum(vector<T> userin, int sumamount, T& total, bool& success);
void getData(vector<T> userin);
};
template <class T>
void computeSum(vector<T> userin, int sumamount, T& total, bool& success)
{
if (sumamount < userin.size()){
success = true;
int i = 0;
while (i<sumamount){
total = total + userin[i];
++i;
}
} else {
success = false;
cerr << "You can not request to sum up more numbers than there are.\n";
}
}
template <class>
void getData(vector<T> userin)
{
cout << "Please insert the data:\n";
int n;
do{
cin >> n;
userin.push_back(n);
} while (n);
cout << "This vector has " << userin.size() << " numbers.\n";
}
int helper()
{
cout << "Do you want help? ";
string help;
cin >> help;
if (help == "n" || help == "no"){
return 0;
}else{
cout << "Enter your data. Negative numbers will be added as 0. Ctrl-D to finish inputing values.\n";
}
}
int main()
{
helper();
getData(userin);
cout << "How many numbers would you like to sum?";
int sumamount;
cin >> sumamount;
computeSum(userin, sumamount);
if (success = true) {
cout << "The sum is " << total << endl;
} else {
cerr << "Oops, an error has occured.\n";
}
cout << endl;
return 0;
}
Outside some flagrantly offensive issues (e.g. it should be template <class T>, not template<class>), the real problem is that vector expects you to push back objects of type T. It looks like you are reading in with type int and pushing. Try:
template <class>
void getData(vector<T> userin)
{
cout << "Please insert the data:\n";
T n;
do{
cin >> n;
userin.push_back(n);
} while (n);
cout << "This vector has " << userin.size() << " numbers.\n";
}
The problem is this line:
userin.push_back(n);
where n is an int. push_back is expecting something of type T.
I'm also not sure what the point of class T is in this case.