Overloading ">>" for a template? - c++

I'm trying to overload the ">>" operator so i can read and store a new Atlas<Animal *> from the keyboard.
The atlas template class has a list in which i'm storing pointers to each Animal object. Here is the code:
class Animal {
protected:
std::string m_name;
public:
Animal() {}
Animal (std::string name): m_name {name} {}
virtual void set_name(std::string name) {m_name = name;}
virtual std::string get_name () {return m_name;}
virtual std::string regn() const { return "???"; }
virtual ~Animal(){
cout << "Destructor animal"<<'\n';}
friend istream& operator >> (istream &in, Animal* k){
in>> k->m_name;
return in;}
}; //pointers to objects from this class will be stored in Atlas2;
//declaration for >> operator
template <class T>
class Atlas2;
template<typename T>
std::istream& operator>>(std::istream& in, const Atlas2<T>& A);
// Template class
template<class T>
class Atlas2{
public:
int nr_pesti;
int m_length;
std::list<T> pages;
Atlas2(){m_length = 0; nr_pesti = 0;}
~Atlas2(){}
void adauga(T data);
Atlas2 operator += (const T& data){
this->m_length++;
this->pages.push_back(data);
return *this;}
friend std::istream& operator>> <> (std::istream& in, const Atlas2<T>& A);
};
template <class T>
istream operator>> (istream &in, const Atlas2<T> &A)
{
in >> A.m_length;
for (int i=1; i<=A.m_length; i++){
T data = new T;
cin >> data;
A.pages.push_back(data);}
return in;
}
template <class T>
void Atlas2<T>::adauga(T data){m_length = m_length+1;
pages.push_back(data);}
// here's the main:
int main(){
Atlas2<Animal *> Atlas3;
cin >> Atlas3;
return 0;}
What am I doing wrong here? I get this error when compiling:
ambiguous overload for 'operator>>' (operand types are 'std::istream' {aka 'std::basic_istream<char>'} and 'Atlas2<Animal*>') at line 58 (Where i type cin>>Atlas3) and these Warnings for the >> operator in the template class : note: candidate: 'std::istream& operator>>(std::istream&, const Atlas2<T>&) [with T = Animal*; std::istream = std::basic_istream<char>]'

Related

Declaration of Array of Pointers Not Being Recognized

using namespace std;
namespace sdds {
const int MAX_NO_OF_ITEMS = 10;
class Menu {
char* m_title;
int indentation;
int m_numofItems;
//issue
MenuItem*m_items = new MenuItem[MAX_NO_OF_ITEMS + 1]; // Declaration of MenuItem type not working
public:
Menu();
Menu(const char* title, int indent = 0);
Menu(const Menu& menu);
~Menu();
bool isEmpty() const;
void add(const char* str);
int run();
ostream& display(ostream& os);
void display() const;
Menu& operator=(const Menu& menu);
operator bool();
operator int();
string& operator=(const char* str);
Menu& operator<<(const char* item);
//friend class MenuItem;
};
class MenuItem {
char* i_name;
//public:
MenuItem();
MenuItem(char*);
MenuItem(const MenuItem& mi);
void setMenuItem(char*);
~MenuItem();
//ostream& display(ostream& os);
ostream& operator<<(ostream& os) const;
istream& operator>>(istream& os) const;
MenuItem& operator=(const MenuItem& mi);
friend class Menu;
};
}
I am trying to make the Menu class hold an array of MenuItem pointers. Menu is a friend of MenuItem. I am having trouble trying to declare this array of pointers as I am receiving errors that tell me 'MenuItem' is not a type. "C4430 missing type specifier - int assumed." "C2143 syntax error: missing ';' before '*'"
and "C2238 unexpected token(s) preceding ';'"
Class MenuItem should be defined first in your case then. It is not known at the time of Declaration
using namespace std;
namespace sdds {
const int MAX_NO_OF_ITEMS = 10;
class Menu;
class MenuItem {
char* i_name;
//public:
MenuItem();
MenuItem(char*);
MenuItem(const MenuItem& mi);
void setMenuItem(char*);
~MenuItem();
//ostream& display(ostream& os);
ostream& operator<<(ostream& os) const;
istream& operator>>(istream& os) const;
MenuItem& operator=(const MenuItem& mi);
friend class Menu;
};
class Menu {
char* m_title;
int indentation;
int m_numofItems;
MenuItem*m_items = new MenuItem[MAX_NO_OF_ITEMS + 1];
public:
Menu();
Menu(const char* title, int indent = 0);
Menu(const Menu& menu);
~Menu();
bool isEmpty() const;
void add(const char* str);
int run();
ostream& display(ostream& os);
void display() const;
Menu& operator=(const Menu& menu);
operator bool();
operator int();
string& operator=(const char* str);
Menu& operator<<(const char* item);
};
}

C++ Trying to add >> Operator Overload To Template

I have a class IPrintable which is a template and a class which derives from it - Date. I want to add the operator >> to the template but keep getting an error:
source.cpp(16): error C2259: 'Date': cannot instantiate abstract class
source.cpp(16): note: due to following members:
source.cpp(16): note: 'void IPrintable<Date>::toIs(std::istream &)': is abstract
iprintable.h(19): note: see declaration of 'IPrintable<Date>::toIs'
I have successfully added the << operator to the template this way:
virtual void toOs(ostream& os) const = 0;
friend ostream& operator << (ostream& output, const IPrintable& toPrint) {
toPrint.toOs(output);
return output;
}
And then I have declared virtual void toOs(ostream& os) const = 0; to date.h and implemented it in date.cpp.
This is my IPrintable.h:
#pragma once
#include <iostream>
#include <string>
using namespace std;
template <class T>
class IPrintable {
private:
public:
virtual void toOs(ostream& os) const = 0;
friend ostream& operator << (ostream& output, const IPrintable& toPrint) {
toPrint.toOs(output);
return output;
}
virtual void toIs(istream& input) = 0;
friend istream& operator >> (istream& input, IPrintable& toSet) {
toSet.toIs(input);
return input;
}
};
This is the declaration of in Date.h, under public:
virtual void toOs(ostream& output) const;
virtual void toIS(istream& input);
This is the implementation of the << (toOs) and >> (toIs) in Date.cpp:
void Date::toOs(ostream& output) const {
if (!isLeapYear(this->getDay(), this->getMonth(), this->getYear())) {
cout << "Not a leap year";
return;
}
output << getDay() << "/" << getMonth() << "/" << getYear();
}
void Date::toIS(istream& input) {
int index;
string str;
input >> str;
index = str.find('/');
this->setDay(stoi(str.substr(0, index)));
str = str.substr(index + 1);
index = str.find('/');
this->setMonth(stoi(str.substr(0, index)));
str = str.substr(index + 1);
this->setYear(stoi(str));
}
Please, if any more information is needed please let me know and I will do my best to provide it.
Thanks!
Your Date::toIS has a capital S, while your IPrintable::toIs does not. If you add override to the declaration of Date::toIS, you would see that it doesn't actually override anything.

How to add an operator<< for templated class?

I need to add operator<< to make my cout working.
Code template.cpp:
#include "maptemplate.h"
int main(void)
{
typedef unsigned int ID; //Identification number of Employee
map_template<ID,Employee> Database; //Database of employees
Database.Add(761028073,Employee("Jan Kowalski","salesman",28)); //Add first employee: name: Jan Kowalski, position: salseman, age: 28,
Database.Add(510212881,Employee("Adam Nowak","storekeeper",54)); //Add second employee: name: Adam Nowak, position: storekeeper, age: 54
Database.Add(730505129,Employee("Anna Zaradna","secretary",32)); //Add third employee: name: Anna Zaradna, position: secretary, age: 32
//cout << Database << endl; //Print databese
//map_template<ID,Employee> NewDatabase = Database; //Make a copy of database
Employee* pE;
pE = Database.Find(510212881); //Find employee using its ID
pE->Position = "salesman"; //Modify the position of employee
pE = Database.Find(761028073); //Find employee using its ID
pE->Age = 29; //Modify the age of employee
//Database = NewDatabase; //Update original database
///cout << Database << endl; //Print original database
cout<<"Wszystko dziala"<<endl;
}
Code: template.h
#include <iostream>
#include <vector>
using namespace std;
// Początek klasy Employee bez template
class Employee
{
private:
public:
Employee(string Name, string Position, int Age);
string Name;
int Age;
string Position;
}; // koniec klasy employee
// Dodanie pól Name, Age, Position
Employee::Employee(string Name, string Position, int Age)
{
this->Name = Name;
this->Age = Age;
this->Position = Position;
}
template <class Key, class T> // template <klucze, dane pracownikow>
class map_template
{
private:
vector<Key> keys; // vector do przechowywania unikalnych kluczy pracowników
vector<T> content; // vector do przechowywania danych pracowników
public:
map_template()
{
}
void Add(Key key, T t);
T* Find(Key key);
}; // koniec klasy map_template
// Dodanie do bazy (Add)
template <class Key, class T>
void map_template<Key, T>::Add(Key key, T t)
{
keys.push_back(key);
content.push_back(t);
}
// Szukanie w bazie (Find)
template <class Key, class T>
T* map_template<Key, T>::Find(Key key)
{
for (unsigned int i = 0; i < keys.size(); i++)
if (keys[i] == key)
{
return &content.at(i);
}
return nullptr;
}
I was thinking how i should look at it. Its my first time using templates so i dont know how operator<< should look like.
Was thinking about something like:
friend ostream & operator<< (ostream & s, teamplate<something>);
But dont really know how to add it.
I need
cout << Database << endl;
to work properly.
Sorry for some polish language comments.
Edit:
I tried putting this friend declaration in the class Employee but i keep getting errors :(
code:
class Employee
{
private:
public:
Employee(string Name, string Position, int Age);
string Name;
int Age;
string Position;
friend ostream &operator << (ostream &out, const map_template<Key, T> &map);
}
errors:
maptemplate.h:49:63: error: ‘Key’ was not declared in this scope
friend ostream &operator << (ostream &out, const map_template<Key, T> &map);
^~~
maptemplate.h:49:68: error: ‘T’ was not declared in this scope
friend ostream &operator << (ostream &out, const map_template<Key, T> &map);
^
maptemplate.h:49:69: error: template argument 1 is invalid
friend ostream &operator << (ostream &out, const map_template<Key, T> &map);
^
maptemplate.h:49:69: error: template argument 2 is invalid
maptemplate.h: In instantiation of ‘std::ostream& operator<<(std::ostream&, const
map_template<Key, T>&):
Should i change the declaration or what? I know that Key and T are in private. Maybe thats the case?
Anyone can help?
I'm a begginer so :/
You want:
template <class Key, class T>
std::ostream& operator << (std::ostream& out, const map_template<Key, T>& map) {
// your logic on how to output the map here...
return out;
}
so your operator<< will work with map_template of any specialization.
Obviously, your friend approach would also be suitable, plus you would actually drop the unnecessary template line. If you place your operator << declaration inside your class, this:
friend std::ostream& operator << (std::ostream& out, const map_template<Key, T>& map) {
// your logic on how to output the map here..
return out;
}
will do just fine. Notice the lack of repeated template <class Key, class T>. Inside your class - those template types are visible and thus you can use them.

output operator overloading for queue class C++

I am trying to overload the << operator in order to print objects of classes, I tried making a friend function of the operator and then declaring it in below the Queue class, I have not written anything inside the code block here is what I have, it wont compile, it will crash instantly, thanks in advance.
#include <string>
#include <vector>
#include <iostream>
using namespace std;
class Employee{
protected:
long empId;
string empName;
string email;
public:
Employee(){}
Employee(long i, string n){
empName = n,
empId =i;
email = "Unknown";
}
};
class Student{
protected:
long stId;
int year;
string email;
string schoolName;
public:
Student(){}
Student(long i, int y, string sn){
stId = i;
year =y;
email = "Unknown";
schoolName=sn;
}
};
template<class T>
class Queue{
protected:
vector<T> theQ;
public:
void Push(T item);
T pop();
void ReadAnItem();
void PrintQ();
**template<T>** edit
friend ostream& operator<< (ostream& is, const Queue<T>& theQ);
};
template<class T>
ostream& operator<< (ostream& os, const Queue<T>& theQ){
**os << theQ.Print();** Edit
return os;
}
template<class T>
void Queue<T>::ReadAnItem(){
T item;
cout << "Enter the data please: " << endl;
cin >> item;
Push(item);
}
template<class T>
void Queue<T>::Push(T item){
theQ.front() = item;
}
template<class T>
void Queue<T>::PrintQ(){
cout << "The content of the array is as follows: " << endl;
for (int i=0; i< theQ.size(); i++){
cout << theQ[i] << **endl;** I get an "invalid overload of endl"
}
}
You should declare that friend function as a template:
template <class U>
friend ostream& operator<< (ostream& is, const Queue<U>& theQ);
Your operator<< function is a template function, so note that inside friend declaration:
friend ostream& operator<< <T>(ostream& is, const Queue<T>& theQ);
This is not the as Andy's variant, as Andy's variant allows this:
#include <iostream>
template <class T>
class A
{
public:
A(T d): data(d){}
private:
// friend is any template instance of function foo, and not just foo<T>!
template <class U>
friend void foo(A<U>& t);
T data;
};
A<int> ai(1);
template <class T>
void foo(A<T>& t)
{
// A<int> will accept foo<double> as friend
std::cout << ai.data << std::endl;
std::cout << t.data << std::endl;
}
int main()
{
A<double> ad(2);
foo(ad);
return 0;
}
However, in my case, you need to add few forward declarations, in order to make this right:
#include <iostream>
// 2. But before that you need to forward-declare your class, so the function
// can know about the class.
template <class T>
class A;
// 1. You need to forward-declare your foo function...
template <class T>
void foo(A<T>& t);
template <class T>
class A
{
public:
A(T d): data(d){}
private:
friend void foo<T>(A<T>& t);
T data;
};
A<int> ai(1);
template <class T>
void foo(A<T>& t)
{
// error: ‘int A<int>::data’ is private within this context
//std::cout << ai.data << std::endl;
std::cout << t.data << std::endl;
}
int main()
{
A<double> ad(2);
foo(ad);
}
Here's your code, but you need more work to do:
#include <string>
#include <vector>
#include <iostream>
using namespace std;
class Employee{
protected:
long empId;
string empName;
string email;
public:
Employee(){}
Employee(long i, string n){
empName = n,
empId =i;
email = "Unknown";
}
};
class Student{
protected:
long stId;
int year;
string email;
string schoolName;
public:
Student(){}
Student(long i, int y, string sn){
stId = i;
year =y;
email = "Unknown";
schoolName=sn;
}
};
template<class T>
class Queue;
template<class T>
ostream& operator<< (ostream& os, const Queue<T>& theQ);
template<class T>
class Queue{
protected:
vector<T> theQ;
public:
void Push(T item);
T pop();
void ReadAnItem();
void PrintQ() const;
friend ostream& operator<< <T> (ostream& is, const Queue<T>& theQ);
};
template<class T>
ostream& operator<< (ostream& os, const Queue<T>& theQ){
// I will just use this, but it should receive ostream
theQ.PrintQ();
return os;
}
template<class T>
void Queue<T>::ReadAnItem(){
T item;
cout << "Enter the data please: " << endl;
cin >> item;
Push(item);
}
template<class T>
void Queue<T>::Push(T item){
// this aint gonna work! Use std::deque and push_front! theQ.front() = item;
}
template<class T>
void Queue<T>::PrintQ() const{
cout << "The content of the array is as follows: " << endl;
for (int i=0; i< theQ.size(); i++){
// You need to overlload operator<< for student to make this work! cout << theQ[i] << endl;
}
}
int main()
{
Queue<Student> s;
s.Push(Student());
std::cout << s;
return 0;
}
Note - this code is not perfect (nor good), it just shows you how to solve this particular problem. You need to move body of PrintQ() method to operator<< or to make your PrintQ to accept and return ostream&. Also, I've already marked it as a const, as it doesn't change state of the class. Also, you don't have operator<< for student, so you are not able to output it into the ostream&. Also, vector.first() = s will always wipe your first element (it will copy s into the first element of the vector using operator=), or it will fail, if there's no first element. I'm sure there's other bugs, but these are only that I saw while trying your program.
Edit
For each different class, you need to have different operator<<. So, change the Student to:
class Student{
protected:
long stId;
int year;
string email;
string schoolName;
friend ostream& operator<<(ostream& os, const Student& s);
public:
Student(){}
Student(long i, int y, string sn){
stId = i;
year =y;
email = "Unknown";
schoolName=sn;
}
};
and add another operator<< body:
ostream& operator<<(ostream& os, const Student& s)
{
os << s.stId << s.year << s.email << std::endl;
return os;
}
Also, do this for Employee. And you should consider moving common fields from Student and Employee to base class Person.

How to read enums from a std::istream in a generic fashion [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Input from stream to enum type
I have several classes with different enums as class members and I want to read the classes from a stream.
The following code shows an exemplary class:
enum enSide{
eLeft,
eRight
};
enum enType{
eConUndefined,
eConRoom
};
class MyClass{
public:
friend std::istream& operator>>(std::istream& in, MyClass& val) {
in >> val.mSide >> val.mType >> val.mTargetId;
return in;
}
MyClass(){}
private:
enSide mSide;
enType mType;
int mTargetId;
};
Unfortunately this does not work since direct reading into an enum Value is not possible (no template for >>).
Thus I created a helper class:
template<class ENUM>
class ScanTo{
public:
friend std::istream& operator>>(std::istream& in, ScanTo<ENUM>& eval) {
unsigned int val;
in >> val;
eval.mrEnum = static_cast<ENUM>(val);
return in;
}
ScanTo(ENUM& eRef):mrEnum(eRef){}
private:
ENUM& mrEnum;
};
Now I can write the code for reading MyClass as follows:
friend std::istream& operator>>(std::istream& in, MyClass& val) {
ScanTo<enSide> scanside(val.mSide);
ScanTo<enType> scantype(val.mType);
in >> scanside >> scantype >> val.mTargetId;
return in;
}
This is already not far from what I wanted but still needs two indirections over the helper class, which cannot be written as temporarys:
friend std::istream& operator>>(std::istream& in, MyClass& val) {
in >> ScanTo<enSide>(val.mSide)>> ScanTo<enType>(val.mType) >> val.mTargetId;
return in;
}
does not compile (gcc 4.43), because a non const reference to a temporary is forbidden as pointed out in the comments.
So here comes the question:
Can this be done easier without resorting to some temporaries and templates as done above?
I think you may write a helper function template:
template <class T>
std::istream& operator >>(std::istream& is, T& t)
{
int i;
is >> i;
t = (T)i;
return is;
}
which makes
in >> val.mSide >> val.mType >> val.mTargetId;
possible.
The best option for you is to define your data members as int, and use type safe accessors to set and retrieve them.
class MyClass{
public:
friend std::istream& operator>>(std::istream& in, MyClass& val) {
in >> val.mSide >> val.mType >> val.mTargetId;
return in;
}
MyClass(){}
enSide side () const { return static_cast<enSide>(mSide); }
void side (enSide v) { mSide = v; }
enType type () const { return static_cast<enType>(mType); }
void type (enType v) { mType = v; }
int targetId () const { return mTargetId; }
void targetId (int v) { mTargetId = v; }
private:
int mSide;
int mType;
int mTargetId;
};
This avoids the temporaries as you desired.