I've made a custom class user, and made a set<user> users in another class dbase. I've successfully overloaded the extraction operator for the class user and now I'm trying to overload the extraction operator for the class dbase.
This is my code:
ostream& operator<< (ostream &out, dbase &db) {
set<user>::iterator it;
for(it=db.users.begin(); it!=db.users.end(); it++)
out<<(*it)<<endl; //error reported on this line
return out;
}
But I keep on getting this error:
error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
This is the operator<< declaration of class user:
ostream& operator<<(ostream &out, user &u) {
cout<<endl;
cout<<"Username: "<<u.uname;
cout<<endl;
return out;
}
Here is the complete code: (ideone)
#include <iostream>
#include <set>
#include <string>
#include <sstream>
using namespace std;
template <class T>
string to_string(T x) {
stringstream ss;
ss<<x;
return ss.str();
}
class date {
int dd,mm,yyyy;
string str_date;
public:
string get_date() {
return to_string(dd)+"-"+to_string(mm)+"-"+to_string(yyyy);
}
friend ostream& operator << (ostream&,date&);
friend istream& operator >> (istream&,date&);
};
ostream& operator<< (ostream &out, date &d) {
out<<d.get_date();
return out;
}
istream& operator>> (istream &in, date &d) {
cin>>d.dd>>d.mm>>d.yyyy;
return in;
}
class user {
string uname, pwd;
string full_name, contact;
static unsigned long long int id;
date dob;
public:
bool operator < (const user &u) const {
if(uname.compare(u.uname)<0) return true;
return false;
}
void set_uname(string u) {
uname = u;
}
void set_attrib() {
string temp_pass;
while(1) {
cout<<"Full Name: ";
cin>>full_name;
cout<<"Password: ";
cin>>temp_pass;
cout<<"Confirm Password: ";
cin>>pwd;
if(pwd.compare(temp_pass))
cout<<"Passwords do not match. Try Again."<<endl;
else break;
}
cout<<"Contact Number: ";
cin>>contact;
cout<<"Date of Birth(dd mm yyyy): ";
cin>>dob;
}
friend ostream& operator<<(ostream&, user&);
};
ostream& operator<<(ostream &out, user &u) {
cout<<endl;
cout<<"Username: "<<u.uname;
cout<<endl;
return out;
}
class dbase {
set<user> users;
public:
void add_user() {
string uname;
user u;
while(1) {
cout<<"Username: ";
cin>>uname;
u.set_uname(uname);
if(users.find(u)==users.end()) {
u.set_uname(uname);
u.set_attrib();
users.insert(u);
break;
}
else
cout<<"Username already exists. Please try a different username."<<endl;
}
}
friend ostream& operator << (ostream&, dbase&);
};
ostream& operator<< (ostream &out, dbase &db) {
set<user>::iterator it;
user u;
for(it=db.users.begin(); it!=db.users.end(); it++)
out<<(*it)<<endl;
return out;
}
int main() {
return 0;
}
So...
Lesson 1
Please post a complete compilable example. In this case, you didn't provide enough information for us to easily debug your code.
For your particular problem, that code would probably look something like this:
#include <iostream>
#include <set>
using namespace std;
class user {
public:
user(int id = 0): id(id) {}
int id;
};
class dbase {
public:
set<user> users;
};
bool operator<(user const & lhs, user const & rhs) {
return lhs.id < rhs.id;
}
ostream& operator<< (ostream &out, user & user) {
return out << "user(" << user.id << ")";
}
ostream& operator<< (ostream &out, dbase &db) {
set<user>::iterator it;
user u;
for(it=db.users.begin(); it!=db.users.end(); it++)
cout<<*it<<endl;
return out;
}
int main() {
dbase db;
db.users.emplace(3);
db.users.emplace(4);
cout << db << endl;
}
Lesson 2
Please post the entire error message that your compiler reports. In this case, it would actually be:
se.cc: In function ‘std::ostream& operator<<(std::ostream&, dbase&)’:
se.cc:28:16: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
cout<<*it<<endl;
^
In file included from /opt/gcc/4.8.1/include/c++/4.8.1/iostream:39:0,
from se.cc:1:
/opt/gcc/4.8.1/include/c++/4.8.1/ostream:602:5: error: initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = user]’
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
Note that I haven't edited the error message in any way. It's possible that there is additional information in the message that you're missing that could be helpful to people trying to answer your question.
Lesson 3
Instead of:
ostream& operator<< (ostream &out, user & user) { ... }
Do:
ostream& operator<< (ostream &out, user const & user) { ... }
Lesson 4
When overloading the stream exaction or stream insertion operators, you should probably never use cout or cerr. Instead, you've passed a stream object into your function. In your case, you've named it with the typical (expected) argument name of out.
So, your two stream insertion operators should have every instance of cout replaced with out.
This will cause your code to work correctly when you extend it to use things like writing the user database to a file using a fstream, or if you wanted to print a message to cerr as well.
Lesson 5
Just to note. This is an issue because *it returns a reference to a const User. So your existing operator<< overload doesn't match, because it wants a non-const version of a User.
Related
Reading some documentation online I found that istream class was part of C++ long before the string class was added. So the istream design recognizes basic C++ types such as double and int, but it is ignorant of the string type. Therefore, there are istream class methods for processing double and int and other basic types, but there are no istream class methods for processing string objects.
My question is if there are no istream class methods for processing string objects, why this program works and how ?
#include <iostream>
int main(void)
{
std::string str;
std::cin >> str;
std::cout << str << std::endl;
return 0;
}
This is possible with the use operator overloading. As shown in the below example, you can create your own class and overload operator>> and operator<<.
#include <iostream>
class Number
{
//overload operator<< so that we can use std::cout<<
friend std::ostream& operator<<(std::ostream &os, const Number& num);
//overload operator>> so that we can use std::cin>>
friend std::istream &operator>>(std::istream &is, Number &obj);
int m_value = 0;
public:
Number(int value = 0);
};
Number::Number(int value): m_value(value)
{
}
std::ostream& operator<<(std::ostream &os, const Number& num)
{
os << num.m_value;
return os;
}
std::istream &operator>>(std::istream &is, Number &obj)
{
is >> obj.m_value;
if (is) // check that the inputs succeeded
{
;//do something
}
else
{
obj = Number(); // input failed: give the object the default state
}
return is;
}
int main()
{
Number a{ 10 };
std::cout << a << std::endl; //this will print 10
std::cin >> a; //this will take input from user
std::cout << a << std::endl; //this will print whatever number (m_value) the user entered above
return 0;
}
By overloading operator>> and operator<<, this allows us to write std::cin >> a and std::cout << a in the above program.
Similar to the Number class shown above, the std::string class also makes use of operator overloading. In particular, std::string overloads operator>> and operator<<, allowing us to write std::cin >> str and std::cout << str, as you did in your example.
Because std::string overload the >> and << operator to return the type std::istream and std::ostream
How they overload it, you can look in this link that Mat gives.
You can create your own class and overload operators, too. Here is an example:
class MyClass
{
int numberOne;
double numberTwo;
public:
friend std::ostream& operator<<(std::ostream &out, const MyClass& myClass);
friend std::istream& operator>> (std::istream& in, MyClass& myClass);
};
// Since operator<< is a friend of the MyClass class, we can access MyClass's members directly.
std::ostream& operator<<(std::ostream &out, const MyClass& myClass)
{
out << myClass.numberOne << ' ' << myClass.numberTwo;
return os;
}
// Since operator>> is a friend of the MyClass class, we can access MyClass's members directly.
std::istream& operator>> (std::istream& in, MyClass& myClass)
{
in >> myClass.numberOne;
in >> myClass.numberTwo;
return in;
}
int main()
{
MyClass myClass;
std::cin >> myClass;
std::cout << myClass;
}
Because of operator overloading.
In your case, including <iostream> will include <string>, a specialization of std::basic_string. And std::basic_string has the non-member functions operator<< and operator>> defined.
Similarly, you can also overload operator<< and operator>> for your own custom types.
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.
I have a simple C++ class, which I'm trying to add stream operators to, so it can be used with cout and cin
#include <iostream>
namespace testing_namespace {
class test {
friend std::ostream &operator<<(std::ostream &os, const test &o);
friend std::istream &operator>>(std::istream &is, test &o);
public:
void doThing();
private:
int member;
};
}
This is the implementation file:
std::ostream &operator<<(std::ostream &os, const testing_namespace::test &o) {
return os << o.member;
}
std::istream &operator>>(std::istream &is, testing_namespace::test &o) {
return is >> o.member;
}
void testing_namespace::test::doThing() {
std::cout << member << " thing" << std::endl;
}
I'm getting an error on compilation:
In function 'std::ostream& operator<<(std::ostream&, const testing_namespace::test&)':
test.cpp:8:20: error: 'int testing_namespace::test::member' is private within this context
return os << o.member;
with a similar error for operator>>. The doThing method compiles with no issues.
I'm not sure what I'm missing here - shouldn't friend functions be able to access the private members of the class test?
You need to define those functions under the namespace too. When you do that, you can omit the name of the namespace from test.
namespace testing_namespace
{
std::ostream &operator<<(std::ostream &os, const test &o) {
return os << o.member;
}
std::istream &operator>>(std::istream &is, test &o) {
return is >> o.member;
}
}
I want to make three[0]='p'; work in the code below. I think I have to make an operator overloading for that but I don't know how to do. What I want to get is to change first index of "Lottery winner!" to 'p'. (To get "pottery winner!").
#include<iostream>
#include<cstring>
using namespace std;
class str
{
char* a;
public:
str(char *aa=""){
this->a = new char[strlen(aa)+1];
strcpy(a,aa);
}
~str(){
delete a;
}
friend ostream& operator<<(ostream &out, str &aa);
friend istream& operator>>(istream &in, str &aa);
};
ostream& operator<<(ostream &out, str &aa){
out<<aa.a;
return out;
}
istream& operator>>(istream &in, str &aa){
in>>aa.a;
return in;
}
void main(){
str three("Lottery winner!");
three[0]='p';
cout<<three<<endl;
}
This is the general signature of the operator[]:
T& operator[](any_type);
In your context it would look like this:
struct str {
...
char& operator[](std::size_t pos) {
return a[pos];
}
};
class str
{
// ...
public:
// ...
char& operator[] (int x)
{
// add array out-of-bounds check here if you like to ...
return a[x];
}
}
operator char*()
{
return a;
}
Could also work
I am having a really hard time with overloading the << operator. I am working on a homework assignment where I can only modify certain portions of the code. Before you ask, I AM stuck using a struct instead of a class. Here are the portions of the affected code:
The calling function is:
/*
* Write a CSV report listing each course and its enrollment.
*/
void generateReport (ostream& reportFile,
int numCourses,
Course* courses)
{
for (int i = 0; i < numCourses; ++i)
{
//courses is an array of "Course" structs
reportFile << courses[i] << endl;
}
}
Here is the .h file:
#ifndef COURSE_H
#define COURSE_H
#include <iostream>
#include <string>
struct Course {
std::string name;
int maxEnrollment;
int enrollment;
Course();
Course(std::string cName);
std::ostream& operator << (ostream &out, const Course &c);
};
#endif
Here is the .cpp file:
#include "course.h"
using namespace std;
Course::Course()
{
name = "";
maxEnrollment = 0;
enrollment = 0;
}
Course::Course(string cName)
{
name = cName;
maxEnrollment = 0;
enrollment = 0;
}
// send course to file
ostream& Course::operator << (ostream &out, const Course &c)
{
out << c.name << "," << c.enrollment << endl;
return out;
}
Here is the error message I keep getting:
error: declaration of 'operator<<' as non-function|
I have been searching the internet for hours and tried lots of different approaches to solve this problem with no success.
Please help!!
I tried a couple of different methods to fix this based on advice. Here are two methods I tried which did not work:
Method 1:
#ifndef COURSE_H
#define COURSE_H
#include <iostream>
#include <string>
struct Course {
std::string name;
int maxEnrollment;
int enrollment;
Course();
Course(std::string cName);
};
//Moved this outside the struct
std::ostream& operator << (ostream &out, const Course &c);
#endif
Method 2 (also failed to change error):
#include "course.h"
using namespace std;
Course::Course()
{
name = "";
maxEnrollment = 0;
enrollment = 0;
}
Course::Course(string cName)
{
name = cName;
maxEnrollment = 0;
enrollment = 0;
}
std::ostream& operator << (ostream &out, const Course &c);
// send course to file
ostream& Course::operator << (ostream &out, const Course &c)
{
out << c.name << "," << c.enrollment << endl;
return out;
}
RE-EDIT--------------------------------------------------------
After some of the comments and help, here is my current code:
In the .h file:
#ifndef COURSE_H
#define COURSE_H
#include <iostream>
#include <string>
struct Course {
std::string name;
int maxEnrollment;
int enrollment;
Course();
Course(std::string cName);
std::ostream& operator << (std::ostream &out, const Course &c);
};
#endif
In the .cpp file:
#include "course.h"
using namespace std;
Course::Course()
{
name = "";
maxEnrollment = 0;
enrollment = 0;
}
Course::Course(string cName)
{
name = cName;
maxEnrollment = 0;
enrollment = 0;
}
// send course to file
ostream& operator << (ostream &out, const Course &c)
{
out << c.name << "," << c.enrollment << endl;
return out;
}
You forgot to include <ostream> and the namespace specifier std:: in your argument, which leads into your error.
Read on if you want to hear about your next error:
std::ostream& operator << (std::ostream &out, const Course &c);
This means that you define an operator which should work on a current instance of a Course as left hand side (*this), since it is defined as a member. This would lead into an operator that has one left hand side and two right hand sides, which isn't possible.
You need to define the operator as a non-member function, since the left hand side should be an ostream& and not Course&.
std::ostream& operator << (std::ostream &out, const Course &c);
should be
friend std::ostream& operator << (std::ostream &out, const Course &c);
And
std::ostream& Course::operator << (std::ostream &out, const Course &c) // Not a member of Course
{
should be
std::ostream& operator << (std::ostream &out, const Course &c)
{
Since it is not a member of Course.
std::ostream& operator << (ostream &out, const Course &c); inside the Course declaration, must be declared as friend, otherwise it cannot take two parameters.
also, the fist parameter must be std::ostream& and not just ostream&