C++ ostream << Operator - c++

I have a Class that deals with Music Albums. The artists and albums are strings. It also has a collection (vector) of tracks called contents. Each track has a title and a duration.
This is my ostream <<:
ostream& operator<<(ostream& ostr, const Album& a){
ostr << "Album: " << a.getAlbumTitle() << ", ";
ostr << "Artist: " << a.getArtistName() << ", ";
ostr << "Contents: " << a.getContents() << ". "; //error thrown here
return ostr;
}
The << next to the a.getContents() is underlined and says: "Error: no operator "<<" matches these operands.
What am I missing out or doing wrong? Can you not use vectors in this way? or maybe its something I'm missing from my Track class?

Assuming Album::getContents() returns std::vector<Track>, you need to provide
std::ostream& operator<<(std::ostream& o, const Track& t);
and
std::ostream& operator<<(std::ostream& o, const std::vector<Track>& v);
where the latter can use the former. For example:
struct Track
{
int duration;
std::string title;
};
std::ostream& operator<<(std::ostream& o, const Track& t)
{
return o <<"Track[ " << t.title << ", " << t.duration << "]";
}
std::ostream& operator<<(std::ostream& o, const std::vector<Track>& v)
{
for (const auto& t : v) {
o << t << " ";
}
return o;
}
There's a C++03 demo here.

If Album::getContents() is about your vector and you just return the vector than ostream does not know how to write it, because there is no '<<' operator.
Just overload the '<<' operator for a vector and you are happy.

Related

Why overloading "<<" needs a const argument? [duplicate]

This question already has an answer here:
c++ overloading stream operator, parameters by reference and anonymous instances
(1 answer)
Closed 3 years ago.
I have a class
class complex
{
[...]
complex operator+(const complex &c) const;
[...]
friend std::ostream &operator<<(std::ostream &os, const complex &c);
};
complex complex::operator+(const complex &c) const
{
complex result;
result.real_m = real_m + c.real_m;
result.imaginary_m = imaginary_m + c.imaginary_m;
return result;
}
std::ostream &operator<<(std::ostream &os, const complex &c)
{
os << "(" << c.real_m << "," << c.imaginary_m << "i)";
return os;
}
int main()
{
complex a(3.0, 4.0);
complex c(5.0, 8.0);
cout << "a is " << a << '\n';
cout << "a + c is " << a + c << '\n';
[...]
}
and, everything works fine, but if i remove const in std::ostream &operator<<(std::ostream &os, const complex &c) the cout << "a is " << a << '\n'; works fine but cout << "a + c is " << a + c << '\n'; doesn't, it say: No operator "<<" matches these operands. Thus, why this doesn't work without const ?
a + c is not an l-value, and so you cannot use a non-const reference on it.

C++ compile error; stream operator overload

I'm learning C++ stream operator overloading. Can't get this to compile in Visual Studio.
In the istream& operator section, the compiler highlights the carats just after ins and says no operator >> matches these operands.
Can someone quick run it and tell me what's wrong?
*****************
// CoutCinOverload.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <fstream>
using namespace std;
class TestClass {
friend istream& operator >> (istream& ins, const TestClass& inObj);
friend ostream& operator << (ostream& outs, const TestClass& inObj);
public:
TestClass();
TestClass(int v1, int v2);
void showData();
void output(ostream& outs);
private:
int variable1;
int variable2;
};
int main()
{
TestClass obj1(1, 3), obj2 ;
cout << "Enter the two variables for obj2: " << endl;
cin >> obj2; // uses >> overload
cout << "obj1 values:" << endl;
obj1.showData();
obj1.output(cout);
cout << "obj1 from overloaded carats: " << obj1 << endl;
cout << "obj2 values:" << endl;
obj2.showData();
obj2.output(cout);
cout << "obj2 from overloaded carats: " << obj2 << endl;
char hold;
cin >> hold;
return 0;
}
TestClass::TestClass() : variable1(0), variable2(0)
{
}
TestClass::TestClass(int v1, int v2)
{
variable1 = v1;
variable2 = v2;
}
void TestClass::showData()
{
cout << "variable1 is " << variable1 << endl;
cout << "variable2 is " << variable2 << endl;
}
istream& operator >> (istream& ins, const TestClass& inObj)
{
ins >> inObj.variable1 >> inObj.variable2;
return ins;
}
ostream& operator << (ostream& outs, const TestClass& inObj)
{
outs << "var1=" << inObj.variable1 << " var2=" << inObj.variable2 << endl;
return outs;
}
void TestClass::output(ostream& outs)
{
outs << "var1 and var2 are " << variable1 << " " << variable2 << endl;
}
operator >>() should take TestClass& instead of const TestClass& as its 2nd parameter since you are expected to modify that parameter while reading from istream.
You should change the parameter type of inObj to reference to non-const, since it's supposed to be modified in operator>>. You can't modify on a const object, so you can't call opeartor>> on const object (and its members), that's what compiler complains.
friend istream& operator >> (istream& ins, TestClass& inObj);
Remove the qualifier const
friend istream& operator >> (istream& ins, const TestClass& inObj);
^^^^^
You may not change a constant object.

Using ostream overloading on pointers to objects

So, I have a struct Bike, which looks like this
struct Bike {
std::string brand;
std::string model;
bool is_reserved;
friend std::ostream& operator<<(std::ostream out, const Bike& b);
};
std::ostream& operator<<(std::ostream out, const Bike& b) {
return out
<< "| Brand: " << b.brand << '\n'
<< "| Model: " << b.model << '\n';
}
And another class BikeRentalService, which has a std::vector<Bike*> called bikes_m. This class also has a method print_available_bikes(), which is supposed to iterate over said std::vector<Bike*> and print each Bike by using the overloaded operator<< shown above. This method looks like that:
void BikeRentalService::print_available_bikes(std::ostream& out) {
if (bikes_m.empty()) {
out << "| None" << '\n';
}
else {
for (auto bike : bikes_m) {
if (!bike->is_reserved) {
out << bike;
}
}
}
}
The problem is that using this function just prints out the addresses of those Bike objects. Dereferencing the objects before using out << does not work either, Visual Studio says it can't reference std::basic_ostream because it is a "deleted function".
Writing the for loop as (auto *bike : bikes_m) does not change anything.
The rigth way to overload the ostream operator is as follows:
struct Bike {
std::string brand;
std::string model;
bool is_reserved;
friend std::ostream& operator<<(std::ostream& out, const Bike& b); // <- note passing out by reference
};
std::ostream& operator<<(std::ostream& out, const Bike& b) {
return out
<< "| Brand: " << b.brand << '\n'
<< "| Model: " << b.model << '\n';
}
Also, as noted by #KyleKnoepfel you should change out << bike; to out << *bike; too.

C++ operator overload doesnt work

I have a question about operators and how to overload them. There is an example of code and I'm overloading operator<< but it doesn't work. There is class that I use:
class CStudent{ //class for students and their attributes
int m_id;
int m_age;
float m_studyAverage;
public:
CStudent(int initId, int initAge, float initStudyAverage): m_id(initId), m_age(initAge), m_studyAverage(initStudyAverage){}
int changeId(int newId){
m_id = newId;
return m_id;
}
int increaseAge(){
m_age++;
return m_age;
}
float changeStudyAverage(float value){
m_studyAverage += value;
return m_studyAverage;
}
void printDetails(){
cout << m_id << endl;
cout << m_age << endl;
cout << m_studyAverage << endl;
}
friend ostream operator<< (ostream stream, const CStudent student);
};
Overload:
ostream operator<< (ostream stream, const CStudent student){
stream << student.m_id << endl;
stream << student.m_age << endl;
stream << student.m_studyAverage << endl;
return stream;
}
And there is main method:
int main(){
CStudent peter(1564212,20,1.1);
CStudent carl(154624,24,2.6);
cout << "Before the change" << endl;
peter.printDetails();
cout << carl;
peter.increaseAge();
peter.changeStudyAverage(0.3);
carl.changeId(221783);
carl.changeStudyAverage(-1.1);
cout << "After the change" << endl;
peter.printDetails();
cout << carl;
return 0;
}
Where is the problem?
The problem here is you need to learn what references are and the difference between std::ostream and std::ostream& is.
std::ostream& operator<< (std::ostream& stream, const CStudent& student)

Overloaded ostream operator segmentation fault if no endl

class foo {
public:
friend ostream& operator << (ostream &os, const foo &f);
foo(int n) : a(n) {}
private:
vector <int> a;
};
ostream& operator << (ostream &os, const foo &f) {
for (int i = 0; i < f.a.size(); ++i)
os << f.a[i] << " ";
os << endl; // why is this line a must?
}
int main(void) {
foo f(2);
cout << f << endl;
return 0;
}
In the above code, if the marked line is removed, there will be a segment fault error, can someone explain why?
ostream& operator << (ostream &os, const foo &f) {
for (int i = 0; i < f.a.size(); ++i)
os << f.a[i] << " ";
os << endl; // why is this line a must?
}
is not manadatory. The segfault is caused because you are not returning os
ostream& operator << (ostream &os, const foo &f) {
for (int i = 0; i < f.a.size(); ++i)
os << f.a[i] << " ";
return os; // Here
}
it is undefined behavior if you don't return the ostream. The endl is flushing your os here. That's why it seems like it is working.
EDIT: Why it is working in this case according to Bo Persson
The os << endl; is another operator call that actually returns os by
placing it "where a return value is expected" (likely a register).
When the code returns another level to main, the reference to os is
still there