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.
Related
Error ocurred with the following try to operator overloading:
#include<iostream>
#include<string>
#include<ostream>
using namespace std;
class Dollar
{
private:
float currency, mktrate, offrate;
public:
Dollar(float);
float getDollar() const;
float getMarketSoums() const;
float getofficialSoums() const;
void getRates();
// In the following function I was trying to overload "<<" in order to print all the data members:
friend void operator<<(Dollar &dol, ostream &out)
{
out << dol.getDollar() << endl;
out << dol.getMarketSoums() << endl;
out << dol.getofficialSoums() << endl;
}
};
Dollar::Dollar(float d)
{
currency = d;
}
float Dollar::getDollar() const
{
return currency;
}
float Dollar::getMarketSoums() const
{
return mktrate;
}
float Dollar::getofficialSoums() const
{
return offrate;
}
void Dollar::getRates()
{
cin >> mktrate;
cin >> offrate;
}
int main()
{
Dollar dollar(100);
dollar.getRates();
// In this line I am getting the error. Could you please help to modify it correctly?
cout << dollar;
system("pause");
return 0;
}
You have to pass std::ostream object as the first parameter to the insertion operator << not as the second one as long as you are calling it that way:
friend void operator << (ostream &out, Dollar &dol);
You should make the object passed in to the insertion operator constant reference as long as this function is only prints and not intending to modify the object's members:
friend void operator << (ostream &out, const Dollar& dol);
So pass by reference to avoid multiple copies and const to avoid unintentional modification.
If you want to invoke to get it work the way you wanted you can do this:
friend void operator<<(const Dollar &dol, ostream &out){
out << dol.getDollar() << endl;
out << dol.getMarketSoums() << endl;
out << dol.getofficialSoums() << endl;
}
And in main for example:
operator << (dollar, cout); // this is ok
dollar << cout; // or this. also ok.
As you can see I reversed the order of calling the insertion operator to match the signature above. But I don't recommend this, it is just to understand more how it should work.
I'm having troubles understanding the reason why the compiler accuses error, when the return type of a << operator overload is std::string. Could you please help me understand?
Bellow is an reproducible example, which gives a gigantic error.
class XY
{
int X__;
int Y__;
public:
XY(int x, int y):X__(x), Y__(y){}
~XY(){}
std::string operator<<(const XY_cartesiano& c)
{
std::stringstream ss;
ss << "{ " << X__ << ", " << Y__ << " }";
return ss.str();
}
int x() const{return X__;}
int y() const{return Y__;}
};
void main()
{
XY a(1,2);
std::cout << a;
}
Let's take something like this as an example:
cout << "My number is " << 137 << " and I like it a lot." << endl;
This gets parsed as
((((cout << "My number is ") << 137) << " and I like it a lot.") << endl);
In particular, notice that the expression cout << "My number is " has to evaluate to something so that when we then try inserting 137 with << 137 the meaning is "take 137 and send it to cout."
Imagine if cout << "My number is " were to return a string. In that case, the << 137 bit would try to use the << operator between a string on the left-hand side and an int on the right-hand side, which isn't well-defined in C++.
The convention is to have the stream insertion operator operator << return a reference to whatever the left-hand side stream is so that these operations chain well. That way, the thing on the left-hand side of << 137 ends up being cout itself, so the above code ends up essentially being a series of chained calls to insert things into cout. The signature of these functions therefore usually look like this:
ostream& operator<< (ostream& out, const ObjectType& myObject) {
// ... do something to insert myObject into out ... //
return out;
}
Now, everything chains properly. Notice that this function is a free function, not a member function, and that the left-hand side is of type ostream and the right-hand side has the type of your class in it. This is the conventional way to do this, since if you try overloading operator << as a member function, the left-hand side will be an operand of your class type, which is backwards from how stream insertion is supposed to work. If you need to specifically access private fields of your class in the course of implementing this function, make it a friend:
class XY {
public:
...
friend ostream& operator<< (ostream& out, const XY& myXY);
};
ostream& operator<< (ostream& out, const XY &myXY) {
...
return out;
}
Correct way to overload << operator in your case is
ostream& operator<<(ostream& os, const XY& c)
{
os << c.X__ <<" "<< c.Y__ ;
return os;
}
You have overloaded operator<< in a way that's incompatible with the conventions you must follow when you intend to use the operator with a std::ostream object like std::cout.
In fact, your operator<<'s signature has nothing to do with streams at all! It is just a member function of XY which takes another XY (which it then does not use), returns a string and has an unsual name. Here's how you would theoretically call it:
XY a(1,2);
XY b(1,2);
std::string x = (a << b);
The correct way to overload operator<< for use with streams is to make the operator a non-member function, add a stream reference parameter and return a stream reference to the stream argument. You also do not need a string stream; you write directly to the stream you get:
#include <iostream>
class XY
{
int x;
int y;
public:
XY(int x, int y) : x(x), y(y) {}
int X() const { return x; }
int Y() const { return y; }
};
std::ostream& operator<<(std::ostream& os, XY const& c)
{
os << "{ " << c.X() << ", " << c.Y() << " }";
return os;
}
int main()
{
XY a(1,2);
std::cout << a;
}
If I want to overload the << operator to use cout on a class, it should look like this:
template <typename coutT>
friend ostream& operator << (ostream &, const vector3D<coutT>&);
inside the class, and
template <typename coutT>
ostream& operator << (ostream & os,const vector3D<coutT>& v)
{
os << "x: " << v.x<< " y: " << v.y << " z: " << v.z;
return os;
}
on the outside. Please take note of the const at the second operand.
This sample of code works just fine. Now to the problem.
If I were to write the overload function using the getters for the fields, instead of addressing them directly (since operator<< is a friend), my compiler would throw an error:
template <typename coutT>
ostream& operator << (ostream & os,const vector3D<coutT>& v)
{
os << "x: " << v.getX() << " y: " << v.getY() << " z: " << v.getZ();
return os;
}
The error:
(VisualStudio2012) errorC2662: "this-pointer cannot be converted from "const vector3D" in "vector3D&""
An important note is that deleting the "const" at the second operand so that it's like
ostream& operator << (ostream & os,vector3D<coutT>& v){...}
ended compiler errors, but since I don't want to change v, it should really be a const.
I should also mention that I think it may have to do with method calls in general, but I'm not sure.
edit:
So it is solved, declaring functions as const sticks to const-correctness.
The error message explains it in the way that it cannot cast the const type to a non-const one.
btw.: I'm actually impressed about the quick responses.
The getter function should be declared const if you want to use it that way.
For example
int getValue() const {
return x;
}
Complete example:
#include <iostream>
#include <vector>
using namespace std;
class Foo {
int x;
public:
Foo(int a) : x(a) {
}
int getValue() const {
return x;
}
friend ostream & operator<<(ostream & out, const Foo & foo) {
return out << foo.getValue();
}
};
int main() {
vector<Foo> foo_vec = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for (vector<Foo>::iterator it = foo_vec.begin(); it != foo_vec.end(); it++) {
cout << *it << ", ";
}
return 0;
}
Your problem is that you didn't mark the get functions const:
They need to look like this:
double getX() const;
You need to make the accessor functions const:
struct V
{
int getX() const { /* ... */ }
^^^^^
};
Only const member functions can be invoked on constant object values. In turn, const member functions cannot mutate the object. Thus const-correctness guarantees that a constant value cannot be mutated by invoking any of its member functions.
I'm a student learning c++. today, I was making a operator overload function to use it in 'cout'. following is a class that contains name, coordinates, etc.
class Custom {
public:
string name;
int x;
int y;
Custom(string _name, int x, int y):name(_name){
this->x = x;
this->y = y;
}
int getDis() const {
return static_cast<int>(sqrt(x*x+y*y));
}
friend ostream& operator << (ostream& os, const Custom& other);
};
ostream& operator << (ostream& os, const Custom& other){
cout << this->name << " : " << getDis() << endl;; // error
return os;
}
However, this code isn't working because of 'THIS' keyword that I was expecting it points to the object. I want to show the object's name and distance value. How can I solve it? I think it is similar with Java's toString method so that it will be able to get THIS.
Thanks in advance for your answer and sorry for poor english. If you don't understand my question don't hesitate to make a comment.
this is available only in member functions, but your operator<< is not a class member (declaring it as friend does not make it a member). It is a global function, as it should be. In a global function, just use the arguments you are passing in:
ostream& operator << (ostream& os, const Custom& other)
{
os << other.name << " : " << other.getDis() << endl;
return os;
}
Also note os replaced cout in the code above. Using cout was an error - the output operator should output to the provided stream, not to cout always.
I'm working in a Big Integer implementation in C++ and I'm trying to use cout with my BigInt class. I already overloaded the << operator but it doesn't work in some cases.
Here is my code:
inline std::ostream& operator << (ostream &stream, BigInt &B){
if (!B.getSign()){
stream << '-';
}
stream << B.getNumber();
return stream;
}
The code above works with:
c = a + b;
cout << c << endl;
But fails with:
cout << a + b << endl;
In the first case the program runs fine, but in the second the compiler gave an error:
main.cc: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
It's possible to overload the << operator for function in both cases?
Methods:
string getNumber ();
bool getSign ();
string BigInt::getNumber (){
return this->number;
}
bool BigInt::getSign (){
return this->sign;
}
As chris already pointed out in comments very quickly (as usual), you have a temporary created in here:
cout << a + b << endl;
You cannot bind that to a non-const reference. You will need to change the signature of your operator overloading by adding the const keyword to the reference.
This code works for me with a dummy BigInt implementation (as you have not shared yours):
#include <iostream>
using namespace std;
class BigInt
{
public:
bool getSign() const { return true; }
int getNumber() const { return 0; }
const BigInt operator+(const BigInt &other) const {}
};
inline std::ostream& operator << (ostream &stream, const BigInt &B){
// ^^^^^
if (!B.getSign()){
stream << '-';
}
stream << B.getNumber();
return stream;
}
int main()
{
BigInt a, b, c;
c = a + b;
cout << c << endl;
cout << a + b << endl;
return 0;
}
But yeah, I agree that the error message is not self-explanatory in this particular case.
Change
inline std::ostream& operator << (ostream &stream, BigInt &B){
to
inline std::ostream& operator << (ostream &stream, BigInt const& B){
c can be a used where BiInt& is expected but a+b cannot be because a+b is a temporary. But it can be used where BigInt const& is expected.