Link to home
Start Free TrialLog in
Avatar of chsalvia
chsalvia

asked on

Problem overloading << operator

I have a class which contains a wchar_t* text buffer.  I've overloaded the << operator so I can wcout the text buffer by typing wcout and the instance of the class name.

I do this by putting the following line outside of the class:

wostream& operator << (wostream& wstrm, buffer& buf) { return wstrm << buffer.data(); }

So if I do:

buffer buf = L"Hello"
wcout << buf << endl;

...it will output properly. The function data() of course is a member function which returns the wchar_t* variable, just like the STL string data().  The problem is, if I try to output a member function which returns an instance of class buffer, the << operator does not work.

For example, say func1() returns an object of type buffer:

buffer func1()
{
      buffer buf;
      //do something with buf
      return buf;
}

If I do:

wcout << buf.func1() << endl;

...it won't compile.  Why doesn't this work?  buf.func1() returns an object of type buffer, and << is overloaded to accept objects of type buffer.

Another option I tried was to make func1 return a reference to buf.  This works if I make the object static, but that causes other problems.
Avatar of jkr
jkr
Flag of Germany image

Could you post more of your code?

#include <iostream>
using namespace std;

class buffer {

public:

//wostream& operator << (wostream& wstrm, buffer& buf) { return wstrm << buf; }

char* data() { return "test";}
buffer func1()
{
     buffer buf;
     //do something with buf
     return buf;
}
};

wostream& operator << (wostream& wstrm, buffer& buf) { return wstrm << "test"; }

int main () {

buffer buf;
wcout << buf << endl;

wcout << buf.func1() << endl;

}

The above compiles without a problem
Also, extending that to

buffer func2()
{
     buffer buf;
     //do something with buf
     return buf;
}

int main () {

buffer buf;
wcout << buf << endl;

wcout << buf.func1() << endl;

wcout << func2() << endl;

}

does not cause any problems. What error exactly are you getting?
Avatar of chsalvia
chsalvia

ASKER

Hmm...maybe this is another gcc thing.  I copied and pasted your code exactly and it didn't compile.  The error message is extremely long:

test.cpp: In function ‘int main()’:
test.cpp:26: error: no match for ‘operator<<’ in ‘std::wcout << buf. buffer::func1()’
/usr/include/c++/4.0.2/bits/ostream.tcc:67: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/bits/ostream.tcc:78: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/bits/ostream.tcc:90: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/bits/ostream.tcc:125: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/bits/ostream.tcc:159: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/bits/ostream.tcc:102: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/ostream:176: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/ostream:187: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/ostream:191: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/ostream:202: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/bits/ostream.tcc:183: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/bits/ostream.tcc:218: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/bits/ostream.tcc:242: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/ostream:217: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/bits/ostream.tcc:265: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/bits/ostream.tcc:288: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/bits/ostream.tcc:311: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
test.cpp:19: note:                 std::wostream& operator<<(std::wostream&, buffer&)
/usr/include/c++/4.0.2/bits/ostream.tcc:571: note:                 std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const char*) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/ostream:447: note:                 std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, char) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
Sorry, the example should be

#include <iostream>
using namespace std;


class buffer {

public:

wchar_t* data() { return L"test";}
buffer func1()
{
     buffer buf;
     //do something with buf
     return buf;
}
};

buffer func2()
{
     buffer buf;
     //do something with buf
     return buf;
}

wostream& operator << (wostream& wstrm, buffer& buf) { return wstrm << buf.data(); }

int main () {

buffer buf;
wcout << buf << endl;

wcout << buf.func1() << endl;

wcout << func2() << endl;

}

Could you try that again?
Do you also have a field named buf or buffer somewhere?  It looks like the compiler sees a buf.buffer somewhere!
>> Could you try that again?

No, it still doesn't compile.  It gives the same template error message.

Does it compile as is in VC?
>> Do you also have a field named buf or buffer somewhere?  It looks like the compiler sees a buf.buffer somewhere!

No, actually that error message was produced from a program containing only the code in jkr's above post, which does not include a function called buffer.  buffer is the name of the class.
Compiles in both VC6 and VC7. BTW, the following

#include <iostream>
using namespace std;


class buffer {

public:

char* data() { return "test";}
buffer& func1()
{
     buffer buf;
     //do something with buf
     return buf;
}
};

     buffer buf;
buffer& func2()
{
     //do something with buf
     return buf;
}

ostream& operator << (ostream& wstrm, buffer& buf) { return wstrm << buf.data(); }

int main () {

buffer buf;
cout << buf << endl;

cout << buf.func1() << endl;

cout << func2() << endl;

}

also works with g++
jkr,

I tried compiling your code also using Borland under Windows, and it returns this (more user-friendly) error:

Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
test.cpp:
Error E2094 test.cpp 32: 'operator<<' not implemented in type 'wostream' for arg
uments of type 'buffer' in function main()
Error E2094 test.cpp 34: 'operator<<' not implemented in type 'wostream' for arg
uments of type 'buffer' in function main()
Error E2134 test.cpp 34: Compound statement missing } in function main()
*** 3 errors in Compile ***

So it can't be a gcc problem.  
>>also works with g++

Okay - I tried that and it compiled with g++.   But I had actually already tried to return a reference.  It compiles with a warning:

test.cpp: In member function ‘buffer& buffer::func1()’:
test.cpp:12: warning: reference to local variable ‘buf’ returned


Before, when I tried returning a reference I let the warning go, but sometimes it returns garbage characters.  So, to fix that I made the variable in func1() to be static - but that caused other strange problems where if I called the function multiple times with different input parameters it would return the same result as the first function call everytime.
Use the 2nd example, the 1st one is buggy.
>>test.cpp:12: warning: reference to local variable ‘buf’ returned

That's why I moved 'buf' out of that function (for testing purposes).
I was using the second example.  It compiles with the warning:

test.cpp: In member function ‘buffer& buffer::func1()’:
test.cpp:12: warning: reference to local variable ‘buf’ returned

I mean...it works, but it gives that warning.  Is that okay?
The example for g++ is completely different - it uses 'char' instead of 'wchar_t', since my g++ here is 2.96

>>I mean...it works, but it gives that warning.  Is that okay?

No, returning a reference to a local object will most likely cause a crash at runtime.
But surely there must be some way of doing this.  I tried compiling the second example (the one posted at 09:14AM PST) in both g++ and Borland, and both returned a similar error.  And returning a reference doesn't work because it returns a local object.

I wonder why it compiles in VC?
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This seems like a strange limitation.  So, you need to make a public member variable and then assign something to it inside the function, in order to wcout to a function that returns an instance of a class?
>>This seems like a strange limitation.  So, you need to make a public member variable and then assign
>>something to it inside the function, in order to wcout to a function that returns an instance of a class?

There is no public member variable in the above. Only the globbal function outside 'buffer' needs a global variable also. Or, a static one.