E0349 no operator "<<" matches these operands [duplicate] - c++

This question already has answers here:
How come a non-const reference cannot bind to a temporary object?
(11 answers)
Error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’
(2 answers)
cannot bind non-const lvalue reference of type to an rvalue of type
(1 answer)
Closed 3 months ago.
I try to overload operator << and ++ (post and pre).
This is part of my code, but I get error "e0349: no operator matches these operands".
Could you tell me where I made a mistake?
(C++, VS2022)
#include <iostream>
#include <string>
using namespace std;
class K {
int x, y;
public:
K(int a, int b) :x(a), y(b) {};
K() :x(0), y(0) {};
K operator++(int);
K& operator++();
friend ostream& operator<< (ostream & str, K & obj);
};
K K::operator++(int) {
K temp(*this);
x += 1;
y += 1;
return temp;
}
K& K::operator++() {
x += 1;
y += 1;
return *this;
}
ostream& operator<<(ostream& str, K& obj) {
str << "[" << obj.x << ", " << obj.y << "]";
return str;
}
int main(int argc, char* argv[])
{
K obj{10, 20};
cout << obj++ << endl; //here I get error
cout << obj << endl;
cout << ++obj << endl;
}

Simply the post-operator++ is written so that it returns a copy of the temporary value which can be used as rvalue but being that the signature of the insertion operator requires a reference of the value, it does not know how to retrieve the data passed as a copy. This is how you should modify the overloading function of the extract operator:
ostream& operator<<(ostream& str, K const& obj) {
str << "[" << obj.x << ", " << obj.y << "]";
return str;
}
You're simply telling the function that the passed value will have a constant reference that it won't change over time. So it is as if you are taking the reference of the copy value. I know it's very tricky as a thing but I should have cleared your minds enough

Related

Error with << operator overload returning a std::string

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;
}

Unable to understand overloading of assignment operator

To understand the working of objects in c++ better, I wrote this piece of code:
using namespace std;
char n[] = "\n";
class T
{
private:
int num;
public:
T ()
{
num = 0;
cout << n << (long)this % 0xFF << " created without param";
}
T (const int param)
{
num = param;
cout << n << (long)this % 0xFF << " created with param = " << param;
}
T (const T& obj)
{
num = obj.num;
cout << n << (long)this % 0xFF << " created as copy of " << (long)&obj % 0xFF;
}
const T& operator= (const T& obj)
{
if (this == &obj)
return *this;
num = obj.num;
cout << n << (long)this % 0xFF << " got assigned the data of " << (long)&obj % 0xFF;
return *this;
}
~T ()
{
cout << n << (long)this % 0xFF << " destroyed";
}
int get () const {return num;}
void set (const int param) {num = param;}
};
T PlusTen (T obj)
{
T newObj(5);
newObj.set( obj.get() +10 );
return newObj;
}
int main ()
{
T a, b(4);
a = b;
a = PlusTen(b);
cout << n;
return 0;
}
Its working fine, but when I remove the const qualifier in "return-type" and "parameter" of overloaded assignment operator like this below:
T& operator= (T& obj) // const removed
{
if (this == &obj)
return *this;
num = obj.num;
cout << n << (long)this % 0xFF << " got assigned the data of " << (long)&obj % 0xFF;
return *this;
}
Then this line of main function gives error:
a = PlusTen(b);
The error message being:
no match for 'operator=' (operand types are 'T' and 'T')
note:
candidate is: T& T::operator=(T&)
no known conversion for argument 1 from 'T' to 'T&'
If operand types of 'T' and 'T' are problematic, how come the line just above it (a = b;) is totally fine? They too are of operand types 'T' and 'T' !!
I found a relevant questoin here but no useful detail there:
why must you provide the keyword const in operator overloads
One person there says that if we don't use const in operator=, we can only use it for non-const objects. But in my case too both sides are non-const. Then why error? Especially when the line just above it, which is identical in operand types, compiles fine?
Compiler used: MinGW
PlusTen(b); is creating a temporary object. Since non-const references can not be bound to temporary objects, operator= can not be called here.
In a = b; b is not a temporary, it's a modifiable object (a so-called l-value). Non-const reference is successfully bound to it, and operator= is called.
For the extra fun, try defining your b as following:
const T b(4);
This function
T PlusTen (T obj)
{
T newObj(5);
newObj.set( obj.get() +10 );
return newObj;
}
returns a temporary object of type T. this temporary object can be bound with a constant reference.
This is important! This is the reason OP is confused!
Non-const references to temporary objects are not allowed in C++ !! In case of a = PlusTen(b);, as PlusTen(b) is a temporary value, the function operator= cannot bind the argument obj to PlusTen(b) value, because obj is non-const whereas PlusTen(b) can only be const.
So the compiler issues an error because the parameter of the assignment operator
T& operator= (T& obj)
^^^^^^
is not a constant reference.
The qualifier const in the return type makes no matter in the context how the operator is used in your program.

operator << overloading often fails if operator is const?

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.

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.

Private members (specifially pointers) cannot be accessed when operator << is overloaded

#include<climits>
class Int
{
int *i, p;
public:
Int(){
i = new int;
}
Int operator=(int a){
*i = a , p = 7;
return *this;
}
friend std::ostream& operator<<(std::ostream& os, const Int& dt);
};
std::ostream& operator<<(std::ostream& os, const Int& int_obj){
// os << int_obj.p << '\n'; // accessible
os << int_obj.*i << '\n'; // ERROR i was not declared int his scope
return os;
}
int main(){
Int i;
i = 5;
std::cout << i;
}
In function ‘std::ostream& operator<<(std::ostream&, const Int&)’:
error: ‘i’ was not declared in this scope
Why can't i access my pointer variables from the reference of this object ?
Use:
os << *int_obj.i << '\n';
int_obj.*i is meaningless, you're asking to use a member *i of int_obj, which is not available
Also, suggested: Precedence table, for why you don't need () for dereferencing
You've misplaced the dereference operator. You wanted this:
os << *int_obj.i << '\n';
That is, dereference int_obj.i.
The expression int_obj.*i applies the operator .* to int_obj and a pointer-to-member i. And since there's no such i declared, the compiler complains.