c++ - Logger for handling both wide and non-wide strings -
i want single logging function/macro similar cout/wcout, can take both std::string , std::wstring (and wchar_t, etc) input. wide inputs converted utf8 before being sent stream. ideally use it:
logger << utf8str << widestr << std::hex << 84 << " blah " << 1.2 << std::endl;
a global overload of operator<< not work me, since collides other parts of project.
i'm trying extend std::ostringstream this:
#include <iostream> #include <sstream> #include <string> #include <locale> #include <codecvt> using namespace std; string wtoutf8(const wstring &wswide) { typedef std::codecvt_utf8<wchar_t> convert_typex; std::wstring_convert<convert_typex, wchar_t> converterx; return converterx.to_bytes(wswide); } struct clogstream : public virtual std::ostringstream { // allow wstrings clogstream& operator<< (const wstring& ws) { *this << wtoutf8(ws); return *this; } // log wide string literals (e.g. l"widestr") , c-style wide strings strings instead of hex pointer address clogstream& operator<< (const wchar_t* p_ws) { *this << wtoutf8(p_ws); return *this; } // log wchar_t character instead of number clogstream& operator<< (const wchar_t wc) { *this << wtoutf8(wstring(&wc,1)); return *this; } }; int main() { string s("narrow "); wstring ws(l"_wide_"); clogstream log; // these seem work how want them log << "narrow"; log << l"_wide_"; log << l"_wide_" << "narrow"; log << ws << l"_wide_"; log << s << "narrow"; log << ws << "narrow"; log << ws << s; // here think maybe compiler uses ostream << instead of operator<< defined clogstream... log << "narrow" << l"_wide"; // outputs wide string hex value (pointer string) //log << s << ws;// won't compile - error: no match 'operator<<' (operand types 'std::basic_ostream<char>' , 'std::wstring {aka std::basic_string<wchar_t>}') cout << log.str();/* output http://coliru.stacked-crooked.com/: narrow_wide__wide_narrow_wide__wide_narrow narrow_wide_narrow_wide_narrow narrow0x4026d4*/ }
this almost works me, except when wide input follows non-wide in same line, compiler stops using operator<< definition want to. explain why happening? there way prevent it, or approach use accomplish goal?
as suggested, tried defining stream operators non-members:
clogstream& operator<< (clogstream& strm, const wstring& ws) { strm << wtoutf8(ws); return strm; } clogstream& operator<< (clogstream& strm, const wchar_t* p_ws) { strm << wtoutf8(p_ws); return strm; } clogstream& operator<< (clogstream& strm, const wchar_t wc) { strm << wtoutf8(wstring(&wc,1)); return strm; }
but exact same output/compiler error.
here's solution ended using:
although works strings/wstrings, fails for:
- things std::endl , other manipulators
- numeric inputs, based on output, think interpreted wide characters.
-
#include <iostream> #include <sstream> #include <string> #include <locale> #include <codecvt> using namespace std; string wtoutf8(const wstring &wswide) { typedef std::codecvt_utf8<wchar_t> convert_typex; std::wstring_convert<convert_typex, wchar_t> converterx; return converterx.to_bytes(wswide); } // part avoid globally overloading std::ostringstream's operators, // restriction elsewhere in project struct clogstream : public virtual std::ostringstream { clogstream& operator<< (const wstring& ws) { *this << wtoutf8(ws); return *this; } // allow wstrings clogstream& operator<< (const wchar_t* p_ws) { *this << wtoutf8(p_ws); return *this; } // c-style wide strings strings instead of hex pointer address clogstream& operator<< (const wchar_t wc) { *this << wtoutf8(wstring(&wc,1)); return *this; } // wchar_t character instead of number }; // wrapping stream prevents output of clogstream& operator<< being interpreted std::ostringstream struct clogger { clogstream s; string str() { return s.str(); } template <class t> clogger& operator<<(t&& x) { s << std::forward<t>(x); return *this; } }; int main() { string s("narrow"); wstring ws(l"_wide_"); clogger log; log << "narrow" << l"_wide" << s << ws; //works log << std::hex << 84; //won't compile log << std::endl; //won't compile log << std::setw(5); //won't compile log << "1679.2='" << 1679.2 << "'"; //outputs character log << "534='" << 534 << "'"; //outputs character cout << "log=\n" << log.str() << "done" << endl; }
Comments
Post a Comment