473,396 Members | 2,115 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

std::operator<<(basic_ostream&, type) vs. std::basic_ostream::operator(type)... ?

Hello.

I tried to overload the operator<< for implicit printing of wchar_t
string on a char stream.
Normally using it on a ostream will succeed as
std::operator<<<std::char_traits<char>
>(std::basic_ostream<char,std::char_traits<char & _Ostr={...}, ___)
will be called.

However, I am using the boost::format library that internally makes use
of a string stream to store the formatted string. There:
std::basic_ostream<char,std::char_traits<char::ope rator<<(___)
will always be called.

On what basis will the compiler choose which kind of operator<< will be
called??

(see test code below)

thanks.
br,
Martin

test code:
###############
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;

// Output wchar_t* strings on char streams instead of formatting as
void* ...
ostream& operator<<(ostream& os, const wchar_t* c_ptr) {
return os << "(TYPE:wchar_t*)"; // placeholder
}

// Boost.Format library
#include <boost/format.hpp>

////////////////////////////////////////
int main(int argc, char* argv[])
{
ostringstream ostr;
ostream& o = ostr;

o << "\nTest of ostream << operator ..." << endl;
wchar_t* wstr = L"Hello world!";
o << "Output of wchar_t* -- " << wstr << endl;
// CALL STACK ...
// (2) opov.exe!std::operator<<<std::char_traits<char>
>(std::basic_ostream<char,std::char_traits<char & _Ostr={...}, const
char * _Val=0x0042f860) Line 747 C++
// (1)
opov.exe!operator<<(std::basic_ostream<char,std::c har_traits<char &
os={...}, const wchar_t * c_ptr=0x0042f8f0) Line 6 + 0xe bytes C++
// (0) opov.exe!main(int argc=1, char * * argv=0x00356828) Line 17 +
0x26 bytes C++

o << "\nTest of boost-library ostream << operator ..." << endl;
o << "Boost formatted wchar_t* -- " << boost::str(boost::format("%1%")
% wstr) << endl;
// CALL STACK ...
// (6) msvcp80d.dll!std::basic_ostream<char,std::char_tra its<char>
>::operator<<(const void * _Val=0x00433a54) Line 456 C++
// (5)
opov.exe!boost::io::detail::put_last<char,std::cha r_traits<char>,wchar_t
*>(std::basic_ostream<char,std::char_traits<char & os={...}, wchar_t
* const & x=0x00433a54) Line 98 + 0x11 bytes C++
// (4)
opov.exe!boost::io::detail::put<char,std::char_tra its<char>,std::allocator<char>,wchar_t
* const &>(wchar_t * const & x=0x00433a54, const
boost::io::detail::format_item<char,std::char_trai ts<char>,std::allocator<char>
& specs={...},
std::basic_string<char,std::char_traits<char>,std: :allocator<char &
res="",
boost::io::basic_altstringbuf<char,std::char_trait s<char>,std::allocator<char>
& buf={...}, std::locale * loc_p=0x00000000) Line 150 + 0x2c bytes C++
// (3)
opov.exe!boost::io::detail::distribute<char,std::c har_traits<char>,std::allocator<char>,wchar_t
* const
&>(boost::basic_format<char,std::char_traits<char> ,std::allocator<char>
& self={...}, wchar_t * const & x=0x00433a54) Line 242 + 0x3f bytes C++
// (2)
opov.exe!boost::io::detail::feed<char,std::char_tr aits<char>,std::allocator<char>,wchar_t
* const
&>(boost::basic_format<char,std::char_traits<char> ,std::allocator<char>
& self={...}, wchar_t * const & x=0x00433a54) Line 251 + 0xd bytes C++
// (1)
opov.exe!boost::basic_format<char,std::char_traits <char>,std::allocator<char>
>::operator%<wchar_t *>(wchar_t * const & x=0x00433a54) Line 64 +
0xd bytes C++
// (0) opov.exe!main(int argc=1, char * * argv=0x00356828) Line 53 C++

// As can be seen on (5) the parameter (now called x) is of type wchar_t*
// However, the basic_ostream operator<<(void*) will be called.

cout << ostr.str();
}
##################
Mar 6 '08 #1
3 4214
On Mar 6, 5:38 pm, "Martin T." <0xCDCDC...@gmx.atwrote:
I tried to overload the operator<< for implicit printing of wchar_t
string on a char stream.
Normally using it on a ostream will succeed as
std::operator<<<std::char_traits<char>
>(std::basic_ostream<char,std::char_traits<char & _Ostr={...}, ___)
will be called.
However, I am using the boost::format library that internally makes use
of a string stream to store the formatted string. There:
std::basic_ostream<char,std::char_traits<char::ope rator<<(___)
will always be called.
On what basis will the compiler choose which kind of
operator<< will be called??
Overload resolution on the set of visible functions.

You have to be very careful here with user defined << operators
on basic types. When << is invoked for a standard type from
within a template, only std:: will be searched at the point of
instantiation, so if the << wasn't defined at the point of
definition, it won't be found.
(see test code below)
test code:
###############
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
// Output wchar_t* strings on char streams instead of formatting as
void* ...
ostream& operator<<(ostream& os, const wchar_t* c_ptr) {
return os << "(TYPE:wchar_t*)"; // placeholder
}
// Boost.Format library
#include <boost/format.hpp>
Except that here, you've declared (and defined, but that doesn't
matter) the operator before including the header. So even in a
template, the compiler should find your declaration, and use it.
(Unless, of course, boost::format was exported---but I get the
same results as you with g++, which doesn't support export.)

If I put the << operator in namespace std (illegal, and
undefined behavior, but you can often get away with it), the
code works (even if the declaration is moved after the include
of boost/format.hpp), but my understanding of the standard is
that this should not be necessary if the declaration precedes
the template definition (which, of course, is in the file
boost/format.hpp).

It seems weird to me, too.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Mar 7 '08 #2
James Kanze wrote:
On Mar 6, 5:38 pm, "Martin T." <0xCDCDC...@gmx.atwrote:
>(snipped)
>On what basis will the compiler choose which kind of
operator<< will be called??

Overload resolution on the set of visible functions.

You have to be very careful here with user defined << operators
on basic types. When << is invoked for a standard type from
within a template, only std:: will be searched at the point of
instantiation, so if the << wasn't defined at the point of
definition, it won't be found.
Ah ok. This kindof makes sense. Thanks for pointing it out explicitly.

>(see test code below)
>test code:
###############
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
>// Output wchar_t* strings on char streams instead of formatting as
void* ...
ostream& operator<<(ostream& os, const wchar_t* c_ptr) {
return os << "(TYPE:wchar_t*)"; // placeholder
}
>// Boost.Format library
#include <boost/format.hpp>

Except that here, you've declared (and defined, but that doesn't
matter) the operator before including the header. So even in a
template, the compiler should find your declaration, and use it.
(Unless, of course, boost::format was exported---but I get the
same results as you with g++, which doesn't support export.)

If I put the << operator in namespace std (illegal, and
undefined behavior, but you can often get away with it), the
code works (even if the declaration is moved after the include
of boost/format.hpp), but my understanding of the standard is
that this should not be necessary if the declaration precedes
the template definition (which, of course, is in the file
boost/format.hpp).

It seems weird to me, too.
Thanks a lot for this explanation!
I sadly had to give up further experiments for now, as my work time is
only limited atm. :/

(The reason I wanted to do this was some functions that return wchar_t*
but my logging is done in char* and in these cases I will get the
wchar_t* formatted as void*, which is obv. not what I want, but the
compiler will not find the code parts where the explicit conversion
wchar_t->char has been forgotten. (as there exists a conversion from
wchar_t* to void*) ... grml ...)
Maybe someone else can clear-up this "weirdness" as it apparently seems
to happen on g++ (you) and on MSVC8 (VS2005) (me) ...

br,
Martin
Mar 7 '08 #3
On 7 mar, 13:18, "Martin T." <0xCDCDC...@gmx.atwrote:
James Kanze wrote:
On Mar 6, 5:38 pm, "Martin T." <0xCDCDC...@gmx.atwrote:
(snipped)
Maybe someone else can clear-up this "weirdness" as it apparently seems
to happen on g++ (you) and on MSVC8 (VS2005) (me) ...
Yes. I'm curious myself, because it does seem to be
intentional. Maybe there's something particular in
boost::format which affects name lookup as well; I didn't have
time to search it in detail to see, but if so, I can't off hand
imagine what it could be.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Mar 7 '08 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Guenther Brunthaler | last post by:
Hi template specialists, I have a problem with the code listed below. What I wanted to do is defining an operator<< that is able to output a 'matrix<ELEMENT_T, INDEX_T>::subrange' object into...
3
by: Sensei | last post by:
Hi. I have a problem with a C++ code I can't resolve, or better, I can't see what the problem should be! Here's an excerpt of the incriminated code: === bspalgo.cpp // THAT'S THE BAD...
8
by: Ook | last post by:
This is my code in it's entireity: #include <iostream> using namespace std; template <typename T> class SortedList { public: friend ostream& operator<< (ostream& os, const SortedList<T>&...
3
by: Carlo Capelli | last post by:
I found a change in the following code, that behaved correctly in VC++ 6. #include <strstream> using namespace std; void main() { char x; ostrstream(x, 100) << "pippo" << "pluto" << ends;...
0
by: Adrian | last post by:
Hi All, I am trying to create an output operator that doesnt rely on the stream type and is also polymorphic. Is there a way to combine these 2 methods so that the polymorphic output operator...
10
by: ozizus | last post by:
I overloaded operator << for STL map successfully: template <typename T1, typename T2ostream & operator << (ostream & o, map <T1,T2& m) { //code } the code works like a charm. Now, I want...
2
by: Adam Nielsen | last post by:
Hi everyone, Following advice previously given in this group, I've created a function that I'm using to "inline" the creation of a string. Regardless of what you think of my method, I'm...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.