Details
-
Improvement
-
Status: Resolved
-
Major
-
Resolution: Cannot Reproduce
-
0.10.0
-
None
-
None
-
None
Description
Mike Jara reported an unexpected behavior on log4cxx-user on 2008-04-24 (http://marc.info/?t=120899966300001&r=1&w=2)
--------
I'm having trouble getting (Windows) MFC or ATL CStrings to log
properly, when using the LOG4CXX_* macros. For example, this will log
the pointer's hex value, rather than the string contents:
CString sMyString(_T("Test CString"));
LOG4CXX_DEBUG(MyLogger, sMyString);
CString does implement a cast operator to LPCTSTR (wchar_t* in my case).
If I explicitly call this, the string logs properly:
CString sMyString(_T("Test CString"));
LOG4CXX_DEBUG(MyLogger, (LPCTSTR)sMyString);
I would expect this cast operator to be implicitly called inside
MessageBuffer, to make the argument comply with the function signature.
I think this is the function that should be called:
WideMessageBuffer& MessageBuffer::operator<<(const wchar_t* msg);
But when I step through in the debugger, I see that there is a global
cast operator called instead. I assume it's a better fit, as far as the
compiler's concerned:
template<class V>
std::ostream& operator<<(MessageBuffer& os, const V& val) {
return ((std::ostream&) os) << val;
I tried commenting this cast operator out, and then I no longer have to
cast my CString! But I'm afraid this was probably put in for a reason,
and I hate to just hack something when I don't completely understand it.
Does anyone know if I can safetly remove this? Looking at the change
list, I see it was added by "carnold" on 11/6/07, revision number
592542.
I'm using the last snapshot before the 0.10 release, by the way.
Any help would be appreciated.
Thanks!
Mike
----------
The problem is that CString is not recognized as a wide-string type and a fallback insertion operator template basically applies operator<<(std::ostream&, CString&). The template made an arbitrary choice that if no other insertion operator was available, then hope that there was an insertion operator for a char* based stream since it would be more likely to be present and functional than std::wostream insertion operator.
Based on the comment, Inserting a Unicode CString into a std::ostream does not transcode the CString into the current code page, but outputs the pointer's hex value (at least for the version of MFC that Mike tried).
A temporary resolution is to define add something like:
#if defined(_UNICODE)
WideMessageBuffer& operator<<(MessageBuffer& buf, const CString& str) {
return buf << (const wchar_t*) str;
}
#else
CharMessageBuffer& operator<<(MessageBuffer& buf, const CString& str) {
return buf << (const char*) str;
}
#endif
However, it would be nice (but maybe not practical) to provide this in the standard headers.
The issues are:
1. log4cxx should not have an MFC dependency, so the insertion operator needs to be implemented on the callers side.
2. log4cxx headers should not include MFC headers exception when explicit that the app is being compiled with MFC.
Will have to explore to come up with a good solution, Possibilities:
Adding operator definition to log4cxx.hw
Adding operator definition to logger.h
Adding macro to control character type used by templated insertion operator
Add mfclogger.h and possibly mfcloggerimpl.h
Attachments
Issue Links
- is duplicated by
-
LOGCXX-329 Microsoft ATL7 string conversion classes and LOG4CXX_ macros
- Resolved