473,378 Members | 1,451 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,378 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 4207
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...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
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: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

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.