Properly overload << operator - c++

I'm quite new to c++ and my current problem is to output a struct using an overloaded operator.
I've tried my best, but apparently it is not enough. Anyone knows why my compiler keeps pushing out this mistake:
\main.cpp|16|error: no match for 'operator<<' (operand types are 'std::basic_ostream' and 'const Eyecolor')|
This is the corresponding code:
#include <iostream>
#include <string>
using namespace std;
enum class Eyecolor {blue, brown, green};
struct PStruct {
string surname;
Eyecolor eyecolor;
double height;
bool gender;
friend std::ostream& operator<<(std::ostream& os, const PStruct& ps);
};
std::ostream& operator<<(std::ostream& os, const PStruct& ps)
{
os << ps.surname << '/' << ps.height << '/' << ps.gender << '/' << ps.eyecolor; //line 16
return os;
}
void print(){
cout << os;
}
int main()
{
return 0;
}
I'm pretty sure i defined the operator<< one line prior to that.
Anyway thanks for the answers in advance

A stripped down version of the error message:
no match for 'operator<<' (operand types are 'std::ostream' and 'const Eyecolor')
----------------------------> ^^
The error complains about missing operator<< for Eyecolor. The one you defined is for PStruct and tries to call the missing operator here:
os << ps.surname << '/' << ps.height << '/' << ps.gender << '/' << ps.eyecolor;
--------------------> ^^
In the same way you defined one for PStruct you need to define one for EyeColor.
Enum to string conversion is a long standing annoyance in C++, you can see how much work one has to put into it to get a generic solution here: enum to string in modern C++11 / C++14 / C++17 and future C++20. Here I am not going into that, but merely show how to get the operator<< working.
Really no offense, but making the operator a friend smells like Cargo Cult Programming. You probably have seen this in examples, and commonly the operator needs to be befriended, but there is no reason to do so in your code. Moreover print() has errors.
A fixed version could look like this:
#include <iostream>
#include <string>
enum class Eyecolor {blue, brown, green};
struct PStruct {
std::string surname;
Eyecolor eyecolor;
double height;
bool gender;
};
std::ostream& operator<<(std::ostream& os, const Eyecolor ec){
switch(ec){
case Eyecolor::blue :
os << "blue";
break;
case Eyecolor::brown :
os << "brown";
break;
case Eyecolor::green :
os << "green";
break;
default:
os << "unknown color";
}
return os;
}
std::ostream& operator<<(std::ostream& os, const PStruct& ps)
{
os << ps.surname << '/' << ps.height << '/' << ps.gender << '/' << ps.eyecolor;
return os;
}
void print(const PStruct& ps){
std::cout << ps;
}
PS:
Why is “using namespace std;” considered bad practice?

Related

How do I properly overload the << operand to produce the desired results?

https://leetcode.com/explore/learn/card/fun-with-arrays/521/introduction/3294/
I'm following this Leetcode course on Arrays and am trying to follow along using C++ as they use Java, but I'm struggling to get past this part. I just want to read items from the pokedex array I made.
The initial error I got was:
No operator << matches these operands.
Array.cpp(16,15) operand types are std::ostream << Pokemon
I then tried to overload the << operator as I've seen other people ask on here, but I'm not getting the output I want. When I compile the program as-is, nothing prints.
Can someone explain what I can do to get the desired output?
Cyndaquill is a fire type at level 5
Also, can someone explain, or point me in the direction of someone who can explain, operator overloading in an easy non-verbose way? A lot of what I've seen on StackOverflow has been overly verbose and confusing. Maybe it's because I'm new to C++, but still.
Array.cpp
#include <iostream>
#include "Array_Header.hpp"
int main() {
Pokemon pokeDex[15];
Pokemon Cyndaquill = Pokemon("Cyndaquill", 5, "Fire");
Pokemon Totodile = Pokemon("Totodile", 5, "Water");
Pokemon Chikorita = Pokemon("Chikorita", 5, "Grass");
pokeDex[0] = Cyndaquill;
pokeDex[1] = Totodile;
pokeDex[2] = Chikorita;
std::cout << pokeDex[0];
std::cout << pokeDex[1];
std::cout << pokeDex[2];
std::cout << pokeDex[3];
}
Array_Header.hpp
#include <string>
class Pokemon {
public:
//variable declarations
std::string name;
int level;
std::string type;
//Constructor for the DVD class
Pokemon(std::string name, int level, std::string type);
Pokemon() = default;
//toString function declaration
std::string toString();
friend std::ostream& operator<<(std::ostream& os, const Pokemon& obj)
{
return os;
};
};
Array_Header.cpp
#include "Array_Header.hpp"
//Constructor Definition
Pokemon::Pokemon(std::string name, int level, std::string type){
this->type = type;
this->level = level;
this->name = name;
};
//toString function definition
std::string Pokemon::toString(){
return this->name + " is a " + this->type + " type at level " + std::to_string(level) + "\n";
};
Your operator overload for << to print to an std::ostream an object of type Pokemon does nothing but return the os parameter. You need to add the logic for printing inside of here, which would look something like this:
friend std::ostream& operator<<(std::ostream& os, const Pokemon& obj)
{
os << obj.toString();
return os;
};

Why this usage string with ostream cause stackoverflow?

I just wondering why this code is incorrect ? It constantly call Foo constructor and cause stack overflow after sometime.
#include <iostream>
using namespace std;
class Foo
{
std::string str;
public:
Foo(const string& s) : str(s)
{
cout << "Foo constructor" << endl;
}
friend ostream& operator<<(ostream& os,const Foo& foo);
};
ostream& operator<<(ostream& os,const Foo& foo)
{
os << foo.str;
return os;
}
int main()
{
Foo foo{"Hello"};
cout << foo;
cin.get();
}
I know, I know it is ok to write
cout << foo.str << endl;
or os << foo.str.c_str();
but I want to know why this error happens..
The program use std::string and its output operator but does not include the header <string>: when using <string> you need to include that header. The fact that std::string seems to be defined by including <iostream> is insufficient. It is also not portable: a different implementation may choose to only declare but not defined std::string (a declaration is needed, though, as some IOStream members to use the type std::string).
If the output operator for std::string isn't found, the expression
out << foo.str
is interpreted as as
out << Foo(foo.str)
as there is an output operator for Foo. Of course, that does result in an infinite recursion.

How to overload << operator without friend function

I am trying to overload << operator to print Currency (user defined type)
#include <iostream>
using namespace std;
struct Currency
{
int Dollar;
int Cents;
ostream& operator<< (ostream &out)
{
out << "(" << Dollar << ", " << Cents << ")";
return out;
}
};
template<typename T>
void DisplayValue(T tValue)
{
cout << tValue << endl;
}
int main() {
Currency c;
c.Dollar = 10;
c.Cents = 54;
DisplayValue(20); // <int>
DisplayValue("This is text"); // <const char*>
DisplayValue(20.4 * 3.14); // <double>
DisplayValue(c); // Works. compiler will be happy now.
return 0;
}
But getting the following error.
prog.cpp: In instantiation of ‘void DisplayValue(T) [with T = Currency]’:
prog.cpp:34:16: required from here
prog.cpp:22:9: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
cout << tValue << endl;
^
In file included from /usr/include/c++/4.8/iostream:39:0,
from prog.cpp:1:
/usr/include/c++/4.8/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 = Currency]’
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
Can anyone help me if i am missing any thing or doing anything wrong here?
First you need to fix the operator by adding Currency const& c as the second parameter (as it come s on the right hand side).
Then you have two options:
1: Add Friend
struct Currency
{
int Dollar;
int Cents;
friend ostream& operator<< (ostream &out, Currency const& c)
{
return out << "(" << c.Dollar << ", " << c.Cents << ")";
}
};
2: Move the definition outside the class
struct Currency
{
int Dollar;
int Cents;
};
ostream& operator<< (ostream &out, Currency const& c)
{
return out << "(" << C.Dollar << ", " << c.Cents << ")";
}
Either works and is fine.
Personally I like option-1 as it documents the tight coupling of the output operator to the class that it is outputting. But this is such a simple case that either works just fine.
The reason that it can not be a member is that the first parameter is a stream (the left hand side value of the operator is the first parameter). This does not work for members as the first parameter is the hidden this parameter. So technically you could add this method to std::ostream. Unfortunately you don't have accesses (and not allowed to) modify std::ostream. As a result you must make it a free standing function.
Example showing it can be a member:
struct X
{
std::ostream operator<<(int y)
{
return std::cout << y << " -- An int\n";
}
};
int main()
{
X x;
x << 5;
}
That works fine here.
This is because the compiler translates
x << 5;
into
// not real code (pseudo thought experiment code).
operator<<(x, 5)
// Equivalent to:
X::operator<<(int y)
// or
operator<<(X& x, int y)
Because x has a member function operator<< this works fine. If x did not have a member function called operator<< then the compiler would look for a free standing function that takes two parameters with X as the first and int as the second.
You don't put it into your class, you put if afterwards. Since your members are public there is no need to declare it a friend:
struct Currency
{
int Dollar;
int Cents;
};
ostream& operator<< (ostream &out, const Currency& c)
{
out << "(" << c.Dollar << ", " << c.Cents << ")";
return out;
}
Overload it like below, and put it outside of class declaration (you don't need friendship!):
ostream& operator<< (ostream &out, const Currency &c)
{ //^^^^^^^^^^^^^^^^
out << "(" << c.Dollar << ", " << c.Cents << ")";
return out;
}
Funny thing with your code is, you have to use the operator like this:
c << cout; // !!
The way you've written your inserter method, the only way to get it to work would be to do:
c << std::cout;
But instead, if you know your inserters won't need to access any private variables, simply do as the other answers say and create a global function that takes both arguments:
std::ostream& operator <<(std::ostream& os, const Currency& c);
#include<iostream>
using namespace std;
class myclass
{
int x;
public:
myclass() //constructor
{
x=5;
}
friend ostream& operator<<(ostream &outStreamObject,myclass &object); //standard way
void operator<<(ostream &outStreamObject) //Another way.
{
outStreamObject<<this->x;
}
};
ostream& operator<<(ostream &outStreamObject,myclass &object)
{
cout<<object.x;
return outStreamObject;
}
int main()
{
//standard way of overload the extraction operator
myclass object1,object2;
cout<<object1<<" "<<object2;
cout<<endl;
//overloading the extraction operator with using friend function
object1.operator<<(cout);
return 0;
}
It is not at all necessary that the insertion and the extraction operators can be overloaded only by using the friend function.
The above code overloads the extraction operator with and without the friend function. The friend function implementation is favoured because cout can be used the way it is used for other datatypes.
Similary you can overload the insertion operator.
You need to make it friend :
Also you need to give it the right arguments. an ostream and the currency.
friend ostream& operator<< (ostream& stream, const Currency& c )
{
stream << "(" << c.Dollar << ", " << c.Cents << ")";
return stream;
}
Edit:
As you can see in the comments, you don't have to make it friend. You can put it outside the structure.
Currency c;
c.Dollar = 10;
c.Cents = 54;
DisplayValue(c); // Works. compiler will be happy now.

Operator Overloading: Ostream/Istream

I'm having a bit of trouble with a lab assignment for my C++ class.
Basically, I'm trying to get the "cout << w3 << endl;" to work, so that when I run the program the console says "16". I've figured out that I need to use an ostream overload operation but I have no idea where to put it or how to use it, because my professor never spoke about it.
Unfortunately, I HAVE to use the format "cout << w3" and not "cout << w3.num". The latter would be so much quicker and easier, I know, but that's not my decision since the assignment necessitates I type it in the former way.
main.cpp:
#include <iostream>
#include "weight.h"
using namespace std;
int main( ) {
weight w1(6);
weight w2(10);
weight w3;
w3=w1+w2;
cout << w3 << endl;
}
weight.h:
#ifndef WEIGHT_H
#define WEIGHT_H
#include <iostream>
using namespace std;
class weight
{
public:
int num;
weight();
weight(int);
weight operator+(weight);
};
#endif WEIGHT_H
weight.cpp:
#include "weight.h"
#include <iostream>
weight::weight()
{
}
weight::weight(int x)
{
num = x;
}
weight weight::operator+(weight obj)
{
weight newWeight;
newWeight.num = num + obj.num;
return(newWeight);
}
TL;DR: how can I make the "cout << w3" line in main.cpp work by overloading the ostream operation?
Thanks in advance!
Make a friend function in your class
friend ostream & operator << (ostream& ,const weight&);
define it as :
ostream & operator << (ostream& os,const weight& w)
{
os<<w.num;
return os;
}
See here
class weight
{
public:
int num;
friend std::ostream& operator<< (std::ostream& os, weight const& w)
{
return os << w.num;
}
// ...
};
Alternately, make a to_string method that converts weight.num to string ;-)

Multiple output operators?

is it possible to define multiple output operators for an enum? I want to use this
std::ostream& operator<< (std::ostream& os, my_enum e);
operator to (1) print a human readable text and to (2) convert it to some code for storing in a database.
Thanks
Create wrappers which will return some object instead of ostream& which will handle printing. In your case it will object for printing humand-readable value and object for printing database code. Here's rough example which prints human-readable form and integer form. ostream_enum_wrapper_human class with its operator << is used for printing human-readable form, class ostream_enum_wrapper_int with its << is used for printing integer code. To switch from ostream& to wrapper, operator << (ostream&, wrappertag) is used, which wraps ostream object inside of wrapper and returns wrapped object. So next << operator is called on wrapper object, not on ostream&, and wrapper class knows how to print value.
#include <iostream>
using namespace std;
class ostream_enum_wrapper_human
{
public:
ostream& out;
ostream_enum_wrapper_human(std::ostream& _out) : out(_out){}
};
class ostream_enum_wrapper_int
{
public:
std::ostream& out;
ostream_enum_wrapper_int(std::ostream& _out) : out(_out){}
};
enum T{zero,one,two};
struct human_readable{} HumanReadable;
ostream_enum_wrapper_human operator << (ostream& out, human_readable){
return ostream_enum_wrapper_human(out);
}
struct print_int{} PrintInt;
ostream_enum_wrapper_int operator << (ostream& out, print_int){
return ostream_enum_wrapper_int(out);
}
ostream& operator << (ostream_enum_wrapper_human out, T t)
{
switch(t) {
case zero: out.out << "zero"; break;
case one: out.out << "one"; break;
case two: out.out << "two"; break;
}
return out.out;
}
ostream& operator << (ostream_enum_wrapper_int out, T t)
{
return out.out << static_cast<int>(t);
}
int main()
{
cout << HumanReadable << zero << PrintInt << zero << HumanReadable << two;
}
prints zero0two
You may take advantage of overloading by the first argument.
//For human-readable output
std::ostream& operator<< (std::ostream& os, my_enum e);
//For database; note the absence VVV of & sign here
std::ostream& operator<< (databasefmt fmt, my_enum e)
{
std::ostream& os = fmt.stream;
// Write data to os
// ...
return os;
}
struct databasefmt{
std::ostream& stream;
databasefmt(std::ostream & s) : stream(s) {};
};
Then write stream modifier that converts the stream to wrapping databasefmt class, so that next output to that modified stream would be database output for you enum. The printing code would look like this:
output_stream << "DATA: "<< database_format << my_enum::Value << "END OF DATA" ;
// Type: std::ostream | databasefmt | std::ostream |
and the wrapper like this:
//Variable is needed to avoid confusing parentheses in output operators
struct databasefmt_converter_t {} database_format;
// we can't return reference, so we just return fairly small instance of wrapper
databasefmt operator<< (std::ostream& os, databasefmt_converter_t const&)
{ return databasefmt(os); }
Sure why not? You would have to create an ostream derived class which implements writing to the database, much the same as ofstream writes to a file. The devil is in the details.
The preferred way is to use std::ios_base::xalloc and then std::ios_base::iword:
int getxalloc()
{
static const int ix = std::ios_base::xalloc();
return ix;
}
enum my_enum
{
zero,
one,
two,
};
std::ostream& operator<<(std::ostream& os, my_enum e)
{
switch (os.iword(getxalloc())
{
default:
case 0:
os << (int)e;
break;
case 1:
switch (e)
{
case zero:
os << "zero";
break;
case one:
os << "one";
break;
case two:
os << "two";
break;
default:
os << "unknown";
break;
}
break;
}
return os;
}
int main()
{
my_enum e = one;
std::cout.iword(getxalloc()) = 0;
std::cout << e << "\n"; // will output "1"
std::cout.iword(getxalloc()) = 1;
std::cout << e << "\n"; // will output "one"
}
After that you could add some fancy manipulator of your own, instead of using std::ios_base::iword directly. Like this:
inline std::ios_base& format_my_enum_as_int(std::ios_base& ib)
{
ib.iword(getxalloc()) = 0;
return ib;
}
inline std::ios_base& format_my_enum_as_string(std::ios_base& ib)
{
ib.iword(getxalloc()) = 1;
return ib;
}
int main()
{
my_enum e = one;
std::cout << format_my_enum_as_int << e << "\n"; // will output "1"
std::cout << format_my_enum_as_string << e << "\n"; // will output "one"
}
This solution is far from perfect; but there is no really nice one to your problem.
class MyClass {...};
namespace xml
{
std::ostream& operator << (std::ostream& os, MyClass& c);
}
namespace text
{
std::ostream& operator << (std::ostream& os, MyClass& c);
}
As you can see I put the stream operators in namespaces. As a result I have to include the namespace into the current one. This is simply done with a simple using declaration.
using namespace xml;
The trick is to put the using declaration in the smalest scope possible.