Connecting Tech Pros Worldwide Forums | Help | Site Map

question regarding operator << overloading

Goran
Guest
 
Posts: n/a
#1: Jun 27 '08
Hi all,

I have a question regarding operator <<.

A lib of mine contains a class with an overloaded operator << as NON-
class member. This would look like:


#include <iostream>
#include <libsomelib.h>

using namespace std;
using namespace SOMELIB;

int main() {

myClass_t myObject;

cout << myObject;

return 0;
}


The example above works fine. But now I'm building a second lib with
newClass_t and myClass_t as private member:


#include <ostream>
#include <libsomelib.h>

class newClass_t {

public:
...
myClass_t GetMyClass() const;
private:
myClass_t itsMyClass;
}

&ostream operator <<(ostream&, const newClass_t&)


The source file:


...

ostream& <<(ostream& aStream, const newClass_t& aNewClass) {

aStream << aNewClass.GetMyClass();

return aStream;
}


OK, now there is a problem. It's the line "aStream <<
aNewClass.GetMyClass();". It does not compile. The error: no match for
»operator<<« in »aStream << newClass_t::GetMyClass()

So the compiler can't find the overloaded operator. Why? It's inside
libsomelib.h. What's wrong?

Thanks for answering

Victor Bazarov
Guest
 
Posts: n/a
#2: Jun 27 '08

re: question regarding operator << overloading


Goran wrote:
Quote:
Hi all,
>
I have a question regarding operator <<.
>
A lib of mine contains a class with an overloaded operator << as NON-
class member. This would look like:
>
>
#include <iostream>
#include <libsomelib.h>
>
using namespace std;
using namespace SOMELIB;
>
int main() {
>
myClass_t myObject;
>
cout << myObject;
>
return 0;
}
>
>
The example above works fine.
You didn't say how your operator<< is declared. It might matter.
Quote:
But now I'm building a second lib with
newClass_t and myClass_t as private member:
>
>
#include <ostream>
#include <libsomelib.h>
>
class newClass_t {
>
public:
...
myClass_t GetMyClass() const;
private:
myClass_t itsMyClass;
}
>
&ostream operator <<(ostream&, const newClass_t&)
>
>
The source file:
>
>
...
>
ostream& <<(ostream& aStream, const newClass_t& aNewClass) {
>
aStream << aNewClass.GetMyClass();
>
return aStream;
}
>
>
OK, now there is a problem. It's the line "aStream <<
aNewClass.GetMyClass();". It does not compile. The error: no match for
»operator<<« in »aStream << newClass_t::GetMyClass()
>
So the compiler can't find the overloaded operator. Why? It's inside
libsomelib.h. What's wrong?
Namespaces? Did you declare your operator<< in your namespace?

Read the FAQ 5.8 please and follow the suggestions.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Goran
Guest
 
Posts: n/a
#3: Jun 27 '08

re: question regarding operator << overloading


[...]
Quote:
You didn't say how your operator<< is declared. It might matter.
[...]
You're right. Here is a new example:

This main() works...

#include ...

using namespace std;
using namespace SOMELIB;

int main() {

myClass_t myObject;

cout << myObject;

return 0;

}

Because next lib works too:

using namespace std;

namespace SOMELIB {

class myClass_t {
...
};
ostream& operator <<(ostream&, const myClass_t&);
}


Now I want to build a new lib...

#include <ostream>
#include <libsomelib.h>

using namespace std;
using namespace SOMELIB;

namespace NEWLIB {

class newClass_t {

public:
...
void AddMyClass(const myClass_t&);
myClass_t GetMyClass() const;
private:
myClass_t itsMyClass;
};
ostream& operator <<(ostream&, const newClass_t&);
}

newClass_t works also fine but one problem! If I use the operator <<
from myClass_t inside the operator << definition from newClass_t I
got the error. The definition looks like:

ostream&
NEWLIB::
operator <<(ostream& aStream, const newClass_t& aNewClass) {

// Here comes the error!
aStream << aNewClass.GetMyClass();

return aStream;
}
Victor Bazarov
Guest
 
Posts: n/a
#4: Jun 27 '08

re: question regarding operator << overloading


Goran wrote:
Quote:
Quote:
>[...]
>You didn't say how your operator<< is declared. It might matter.
>[...]
>
You're right. Here is a new example:
>
This main() works...
>
#include ...
>
[..]
I am sorry. I probably wasn't clear enough. The information you've
provided is good, but I just don't have time to fill in all the "..."
that you have left in there before I can run it through my compiler,
sorry. And without running it through the compiler I can't even confirm
that the error is the one you're asking about.

Please don't get me wrong, but unless you invest some of *your* time
reducing your code to the bare minimum yet still exhibiting the problem
you're describing (do see the FAQ 5.8 please), how can you expect us to
invest *our* time to help you, really? Start by creating a new file (or
files) that should represent your project in miniature. You can copy
the code from your existing project, I am sure of it. Then remove all
the stuff that is not relevant. Then make sure it all compiles _except_
for the problem you're experiencing. If by then you haven't figured out
what is wrong, post that new, stripped down, code here and ask your
question again. You have to understand that only you have the advantage
of being able to take the non-working code and compile it. Share the
advantage with the newsgroup and the newsgroup will happily share their
knowledge with you. Fair?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Goran
Guest
 
Posts: n/a
#5: Jun 27 '08

re: question regarding operator << overloading


// You are right! I'm a lazy dude :D. Here's a correct example which
does not
// compile! The error:
// main.c++: In function »std::ostream&
BADLIB::operator<<(std::ostream&, BADLIB::BadClass_t&)«:
// main.c++:110: Error: no match for »operator<<« in »aStream <<
BADLIB::BadClass_t::GetValue() const()«

#include <iostream>
#include <string>
#include <ostream>




//// START GOOD CLASS ////

// The GoodClass_t is nothing special but the overloaded operator <<.
// The operator calls the method SetMode and GetMode to change the
output.
using namespace std;

namespace GOODLIB {

class GoodClass_t {

public:
GoodClass_t();
string GetValue() const;
void SetMode(const bool&);
bool GetMode() const;
private:
string itsValue;
bool itsMode;
};
// this operator works
ostream& operator <<(ostream&, GoodClass_t&);
}

GOODLIB::
GoodClass_t::
GoodClass_t() {

itsValue = "foo";
itsMode = true;
}

string
GOODLIB::
GoodClass_t::
GetValue() const {

return itsValue;
}

bool
GOODLIB::
GoodClass_t::
GetMode() const {

return itsMode;
}

void
GOODLIB::
GoodClass_t::
SetMode(const bool& aMode) {

itsMode = aMode;
}

ostream&
GOODLIB::
operator <<(ostream& aStream, GoodClass_t& aWC) {

if(aWC.GetMode()) {
aWC.SetMode(false);
aStream << "Begin Opening (" << aWC.GetValue() << ") End Opening
\n";
}
else {
aWC.SetMode(true);
aStream << "Begin Closing (" << aWC.GetValue() << ") End Closing
\n";
}

return aStream;
}
//// END GOOD CLASS ////




//// START BAD CLASS////

// The BadClass_t contains a private GoodClass_t Object available by
// GetValue(). So it's very simple. But in conjunction with
GoodClass_t I
// really don't know where's the failure.
using namespace std;
using namespace GOODLIB;

namespace BADLIB {

class BadClass_t {

public:
BadClass_t(const GoodClass_t&);
GoodClass_t GetValue() const;
private:
GoodClass_t itsGoodObj;
};
ostream& operator <<(ostream&, /* const */ BadClass_t&);
}

BADLIB::
BadClass_t::
BadClass_t(const GoodClass_t& aGoodObj)
: itsGoodObj(aGoodObj) {

}

GoodClass_t
BADLIB::
BadClass_t::
GetValue() const {

return itsGoodObj;
}

ostream&
BADLIB::
operator <<(ostream& aStream, /* const */ BadClass_t& aBC) {

aStream << aBC.GetValue() << "\nsome stuff\n" << aBC.GetValue();
}
//// END BAD CLASS////


using namespace std;
using namespace GOODLIB;
using namespace BADLIB;

int main() {

GoodClass_t aGoodObj;
BadClass_t aBadObj(aGoodObj);

// Begin Opening (foo) End Opening
// Begin Closing (foo) End Closing
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cout << aGoodObj << aGoodObj; // Works fine

cout << aBadObj; // BAD!!! WHY???

return 0;
}
Victor Bazarov
Guest
 
Posts: n/a
#6: Jun 27 '08

re: question regarding operator << overloading


Goran wrote:
Quote:
// main.c++: In function »std::ostream&
BADLIB::operator<<(std::ostream&, BADLIB::BadClass_t&)«:
// main.c++:110: Error: no match for »operator<<« in »aStream <<
BADLIB::BadClass_t::GetValue() const()«
It would be also good to know which line is 110, don't you think?
Quote:
[..]
namespace GOODLIB {
>
class GoodClass_t {
>
public:
GoodClass_t();
string GetValue() const;
void SetMode(const bool&);
bool GetMode() const;
private:
string itsValue;
bool itsMode;
};
// this operator works
ostream& operator <<(ostream&, GoodClass_t&);
Note that 'GoodClass_t' object is *non-const*. Is there a reason
why this is so?
Quote:
}
>
[..]
void
GOODLIB::
GoodClass_t::
SetMode(const bool& aMode) {
>
itsMode = aMode;
}
>
ostream&
GOODLIB::
operator <<(ostream& aStream, GoodClass_t& aWC) {
>
if(aWC.GetMode()) {
aWC.SetMode(false);
So, while *outputting* an object you *set* its mode? I don't know.
Does not seem like a good idea. Anyway...
Quote:
aStream << "Begin Opening (" << aWC.GetValue() << ") End Opening
\n";
}
else {
aWC.SetMode(true);
aStream << "Begin Closing (" << aWC.GetValue() << ") End Closing
\n";
}
>
return aStream;
}
//// END GOOD CLASS ////
>
>
>
>
//// START BAD CLASS////
>
// The BadClass_t contains a private GoodClass_t Object available by
// GetValue(). So it's very simple. But in conjunction with
GoodClass_t I
// really don't know where's the failure.
using namespace std;
using namespace GOODLIB;
>
namespace BADLIB {
>
class BadClass_t {
>
public:
BadClass_t(const GoodClass_t&);
GoodClass_t GetValue() const;
So, this class returns an rvalue as well...
Quote:
private:
GoodClass_t itsGoodObj;
};
ostream& operator <<(ostream&, /* const */ BadClass_t&);
}
>
[..]
ostream&
BADLIB::
operator <<(ostream& aStream, /* const */ BadClass_t& aBC) {
>
aStream << aBC.GetValue() << "\nsome stuff\n" << aBC.GetValue();
So, let's examine this. 'aBC.GetValue()' returns a temporary,
which you try to pass to the op<< that expects an lvalue. The
argument of the op<< is a reference to non-const that cannot be
bound to a temporary.

You need to revise your interface.
Quote:
}
//// END BAD CLASS////
[..]
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


Goran
Guest
 
Posts: n/a
#7: Jun 27 '08

re: question regarding operator << overloading


First... thanks for your detailed description, Victor!

Regarding your questions:
[...]
Quote:
It would be also good to know which line is 110, don't you think?
[...]
The Line 110 is:
aStream << aBC.GetValue() << "\nsome stuff\n" << aBC.GetValue();


[...]
Quote:
Quote:
ostream& operator <<(ostream&, GoodClass_t&);
>
Note that 'GoodClass_t' object is *non-const*. Is there a reason
why this is so?
[...]
This is due to the fact that a private member is changed.

[...]
Quote:
Quote:
ostream&
GOODLIB::
operator <<(ostream& aStream, GoodClass_t& aWC) {
>
Quote:
if(aWC.GetMode()) {
aWC.SetMode(false);
>
So, while *outputting* an object you *set* its mode? I don't know.
Does not seem like a good idea. Anyway...
[...]
Yeah, because there are two ways of output. E.g. Line 110.

I hope answered all questions. Your analyze below is instructive.
Quote:
[...]
Quote:
ostream&
BADLIB::
operator <<(ostream& aStream, /* const */ BadClass_t& aBC) {
>
Quote:
aStream << aBC.GetValue() << "\nsome stuff\n" << aBC.GetValue();
>
So, let's examine this. 'aBC.GetValue()' returns a temporary,
which you try to pass to the op<< that expects an lvalue. The
argument of the op<< is a reference to non-const that cannot be
bound to a temporary.
>
You need to revise your interface.
>[...]
I will do so.

Greetings, Goran
Victor Bazarov
Guest
 
Posts: n/a
#8: Jun 27 '08

re: question regarding operator << overloading


Goran wrote:
Quote:
First... thanks for your detailed description, Victor!
>
Regarding your questions:
[...]
Quote:
>It would be also good to know which line is 110, don't you think?
[...]
The Line 110 is:
aStream << aBC.GetValue() << "\nsome stuff\n" << aBC.GetValue();
It's too late, isn't it? Just remember to point out certain things you
get for free while in your development environment, to us who can't see
into your monitor from *that afar*.
Quote:
[...]
Quote:
Quote:
>> ostream& operator <<(ostream&, GoodClass_t&);
>Note that 'GoodClass_t' object is *non-const*. Is there a reason
>why this is so?
[...]
This is due to the fact that a private member is changed.
I get that. The reason I asked the question so you would stop and think
whether you actually need to _change_ that private member during output.
Quote:
[...]
Quote:
Quote:
>>ostream&
>>GOODLIB::
>>operator <<(ostream& aStream, GoodClass_t& aWC) {
>> if(aWC.GetMode()) {
>> aWC.SetMode(false);
>So, while *outputting* an object you *set* its mode? I don't know.
>Does not seem like a good idea. Anyway...
[...]
Yeah, because there are two ways of output. E.g. Line 110.
I think what you're saying here is that you need the *alternating* way
of outputting each object. I've never has the need to do that with any
of my objects, but I concede there may be a need. I would, however, in
that case define the 'mode' a *mutable* member of your class and make
'SetMode' a const member and declare the 'aWC' argument a reference to
*const* object.
Quote:
Quote:
>>
>You need to revise your interface.
>[...]
I will do so.
Take a closer look at the 'mutable' suggestion.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Frank Birbacher
Guest
 
Posts: n/a
#9: Jun 27 '08

re: question regarding operator << overloading


Hi!

Victor Bazarov schrieb:
Quote:
I think what you're saying here is that you need the *alternating* way
of outputting each object. I've never has the need to do that with any
of my objects, but I concede there may be a need. I would, however, in
that case define the 'mode' a *mutable* member of your class and make
'SetMode' a const member and declare the 'aWC' argument a reference to
*const* object.
Or you create two separate output functions (not operator <<) and a
separate function object with external state. I'm afraid keeping the
output mode in the object is not reentrant.


Well, Goran, first try the mutable concept.

Frank
Closed Thread


Similar C / C++ bytes