Compilation Error in overloading operator - c++

Not able to understand why getting error
error: no match for ‘operator<<’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream’} and ‘MyStruct’)
cout << st;
in the below code
#include <iostream>
using namespace std;
struct MyStruct
{
int a;
string b;
double c;
MyStruct(int a, string b, double c):a(a),b(b),c(c){}
ostream& operator<<(ostream& os)
{
os << "a " << a << " b" << b << " c" << c;
return os;
}
};
template <typename T, typename ... Args>
T create(Args&& ... Arg)
{
return T(Arg...);
}
int main() {
// your code goes here
MyStruct st = create<MyStruct>(5, "My Struct", 2.5);
cout << st;
return 0;
}

The correct signature for the operator is:
friend ostream& operator<<(ostream& os, const MyStruct& dt);
Right now your output stream operator is only overloaded in a way that allows st << cout.

Related

How to rectify private error while using Friend Function in C++?

Getting this error while using friend function in C++ : error: ‘int complex::a’ is private within this context. How will I rectify this error? I have created one complex class and while learning a friend function, i get to know that friend function can access private member functions too. But in this code, this error pops out. Thanks in advance.
#include <iostream>
using namespace std;
class complex{
private:
int a, b;
public:
void setNumber(int x,int y){a=x;b=y;}
void getNumber(){cout << "\n a="<< a << "b=" << b; }
friend ostream& operator <<(ostream&, complex);
friend istream& operator >>(istream&, complex&);
};
ostream& operator <<(ostream &dout, complex c){
cout << "a=" << c.a;
cout << "b=" << c.b;
return (dout);
}
istream& operator <<(istream &din, complex &c){
cin>>c.a>>c.b;
return (din);
}
int main(){
complex c1;
cin >> c1;
cout << c1;
return 0;
}
change this
ostream& operator <<(ostream &dout, complex c)
{
cout << "a=" << c.a;
cout << "b=" << c.b;
return (dout);
}
istream& operator <<(istream &din, complex &c)
{
cin>>c.a>>c.b;
return (din);
}
to
ostream& operator <<(ostream &dout, const complex& c)
{
dout << "a=" << c.a;
dout << "b=" << c.b;
return (dout);
}
istream& operator >>(istream &din, complex &c)
{
din>>c.a>>c.b;
return (din);
}

How to create a lambda for ostream?

I thought the call of the operator<< would generate a two-parameter function call. So, why does this not compile, then?
#include <iostream> // ostream
#include <iomanip> // setw, setfill
using std::ostream; using std::setw; using std::setfill;
struct Clock {
int h_, m_, s_;
Clock(int hours, int minutes, int seconds)
: h_{hours}, m_{minutes}, s_{seconds} {}
void setClock(int hours, int minutes, int seconds) {
h_ = hours; m_ = minutes; s_ = seconds;
}
friend ostream& operator<<(ostream&os, const Clock& c) {
auto w2 = [](ostream&os, int f) -> ostream& {
return os << setw(2) << setfill( '0' ) << f; };
return os << w2(c.h_) <<':'<<w2(c.m_)<<':'<<w2(c.s_); // ERROR
}
};
The error is (gcc-6)
$ g++-6 -std=gnu++1y ...
file.cpp: In function ‘std::ostream& operator<<(std::ostream&, const Clock&)’:
file.cpp:745:33: error: no match for call to ‘(operator<<(std::ostream&, const Clock&)::<lambda(std::ostream&, int)>) (const int&)’
return os << w2(c.h_) <<':'<<w2(c.m_)<<':'<<w2(c.s_);
^
I also tried the call os << w2(os,c.h_) but gcc and I agreed that was nonsense. Also I tried the lambda as auto as possible:
auto w2 = [](auto&os, auto f) {
return os << setw(2) << setfill( '0' ) << f; };
also no luck.
Any hints?
I thought the call of the operator<< would generate a two-parameter function call.
No, invoking an overloaded operator<< is basically the same as invoking a binary function:
a << b;
// is equivalent to
operator<<(a, b);
// or to
a.operator<<(b);
What you're trying to do is invoke operator<< using a lambda that returns an ostream& as the right-hand argument, but you're not passing the ostream& argument to the lambda itself.
os << w2(os,c.h_) is syntactically valid, but will not compile because there is no operator<<(ostream&, ostream&) definition.
What you can do is simply invoke the lambda without streaming it:
friend ostream& operator<<(ostream&os, const Clock& c) {
auto w2 = [](ostream&os, int f) -> ostream& {
return os << setw(2) << setfill( '0' ) << f; };
w2(os, c.h_);
os <<':';
w2(os, c.m_);
os << ':';
return w2(os, c.s_);
}
wandbox example
If you want to achieve your desired syntax, you will need a little more work. Here's a possible solution:
template <typename TF>
struct streamable : TF
{
streamable(TF&& f) : TF{std::move(f)} { }
};
template <typename TF>
auto& operator<<(ostream& os, const streamable<TF>& s)
{
s(os); return os;
}
template <typename TF>
auto make_streamable_impl(TF f)
{
return streamable<TF>(std::move(f));
}
template <typename TF>
auto make_streamable(TF f)
{
return [&](auto&& x) mutable
{
return make_streamable_impl([&](ostream& os) -> auto&
{
f(os, x);
return os;
});
};
}
Usage:
friend ostream& operator<<(ostream&os, const Clock& c) {
auto w2 = make_streamable([](ostream&os, int f) -> ostream& {
return os << setw(2) << setfill( '0' ) << f; });
return os << w2(c.h_) <<':'<<w2(c.m_)<<':'<<w2(c.s_);
}
wandbox example
Note that a real implementation should probably perfectly-capture the arguments into the lambdas.
This compiles:
friend ostream& operator<<(ostream&os, const Clock& c) {
auto w2 = [](ostream&os, int f) -> ostream& {
return os << setw(2) << setfill( '0' ) << f; };
return w2( os, c.h_ );
}

Pass this to overloaded << operator

How can I pass this to operator<< in c++ class? Or am I just doing this wrong (likely).
For example, in the following class I just have a loop that repetitively asks for and prints an integer. However, cout<<this just prints the address of the instance, but I would like to use the defined operator overload.
#include<iostream>
using std::cout; using std::endl; using std::cin;
class C {
int n;
public:
C(int n) : n(n) {};
friend std::ostream& operator<<(std::ostream&, const C&);
void set_n(int i) { n = i; }
void play() {
int input;
while (true) {
cout << this;
cin >> input;
set_n(input);
}
}
};
std::ostream& operator<<(std::ostream& os, const C& c) {
cout << c.n << "\n";
return os;
}
int main(int argc, char *argv[]) {
C c = C(1);
c.play();
return 0;
}
this is a pointer. You need
cout << *this;
Also, your definition of operator<< should probably use the parameter os rather than always using cout.
this is a pointer. You probably need to dereference it.
cout << *this;

Problems with ostream

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.

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.