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.
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.
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?
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?
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/bit s/ostream. tcc:67: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std:: basic_ostr eam<_CharT , _Traits>& (*)(std::basic_ostream<_Ch arT, _Traits>&)) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/bit s/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/bit s/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/bit s/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/bit s/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/bit s/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/ost ream: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/ost ream: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/ost ream: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/ost ream:202: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsig ned int) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/bit s/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/bit s/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/bit s/ostream. tcc:242: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(doubl e) [with _CharT = wchar_t, _Traits = std::char_traits<wchar_t>]
/usr/include/c++/4.0.2/ost ream: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/bit s/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/bit s/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/bit s/ostream. tcc:311: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std:: basic_stre ambuf<_Cha rT, _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/bit s/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/ost ream: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>]
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/bit
/usr/include/c++/4.0.2/bit
/usr/include/c++/4.0.2/bit
/usr/include/c++/4.0.2/bit
/usr/include/c++/4.0.2/bit
/usr/include/c++/4.0.2/bit
/usr/include/c++/4.0.2/ost
/usr/include/c++/4.0.2/ost
/usr/include/c++/4.0.2/ost
/usr/include/c++/4.0.2/ost
/usr/include/c++/4.0.2/bit
/usr/include/c++/4.0.2/bit
/usr/include/c++/4.0.2/bit
/usr/include/c++/4.0.2/ost
/usr/include/c++/4.0.2/bit
/usr/include/c++/4.0.2/bit
/usr/include/c++/4.0.2/bit
test.cpp:19: note: std::wostream& operator<<(std::wostream&,
/usr/include/c++/4.0.2/bit
/usr/include/c++/4.0.2/ost
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?
#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!
ASKER
>> 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?
No, it still doesn't compile. It gives the same template error message.
Does it compile as is in VC?
ASKER
>> 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.
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++
#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++
ASKER
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.
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.
ASKER
>>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.
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).
That's why I moved 'buf' out of that function (for testing purposes).
ASKER
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?
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.
>>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.
ASKER
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?
I wonder why it compiles in VC?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
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.
>>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.
#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