Hide operator<<() overloads for wxString and related classes
As not defining operator<<() overload taking wxScopedCharBuffer in the global scope prevents it from being considered as an overload resolution candidate (which is, of course, the whole point), it also prevents it from being used for the classes convertible to it, such as wxCharBuffer, so we need to define operator<<() overloaded for the latter explicitly too. We also need a new wxScopedCharTypeBufferStreamSupport helper in order to define different operators inside different specializations of wxScopedCharTypeBuffer<>.
This commit is contained in:
parent
3b62433a3f
commit
2349586e28
3 changed files with 112 additions and 24 deletions
|
|
@ -13,6 +13,10 @@
|
|||
#include "wx/defs.h"
|
||||
#include "wx/wxcrtbase.h"
|
||||
|
||||
#if wxUSE_STD_IOSTREAM
|
||||
#include "wx/iosfwrap.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> // malloc() and free()
|
||||
|
||||
class WXDLLIMPEXP_FWD_BASE wxCStrData;
|
||||
|
|
@ -55,14 +59,70 @@ struct UntypedBufferData
|
|||
// NB: this is defined in string.cpp and not the (non-existent) buffer.cpp
|
||||
WXDLLIMPEXP_BASE UntypedBufferData * GetUntypedNullData();
|
||||
|
||||
// Implementation of stream insertion operators: they can't be inline because
|
||||
// we don't have full std::ostream declaration here.
|
||||
#if wxUSE_STD_IOSTREAM
|
||||
WXDLLIMPEXP_BASE std::ostream& OutputCharBuffer(std::ostream&, const char* s);
|
||||
WXDLLIMPEXP_BASE std::ostream& OutputWCharBuffer(std::ostream&, const wchar_t* ws);
|
||||
#if defined(HAVE_WOSTREAM)
|
||||
WXDLLIMPEXP_BASE std::wostream& OutputWCharBuffer(std::wostream&, const wchar_t* ws);
|
||||
#endif // defined(HAVE_WOSTREAM)
|
||||
#endif // wxUSE_STD_IOSTREAM
|
||||
|
||||
} // namespace wxPrivate
|
||||
|
||||
|
||||
// Template used as CRTP base class for wxScopedCharTypeBuffer in order to
|
||||
// define overloaded operator<<() for it.
|
||||
//
|
||||
// By default we don't define any operators, but we do define them for the
|
||||
// usual char and wchar_t specializations below.
|
||||
template <typename T, typename Buffer>
|
||||
struct wxScopedCharTypeBufferStreamSupport
|
||||
{
|
||||
};
|
||||
|
||||
// Suppress the warning about declaring a non-template friend because this is
|
||||
// exactly what we want to do here.
|
||||
wxGCC_ONLY_WARNING_SUPPRESS(non-template-friend)
|
||||
|
||||
template <typename Buffer>
|
||||
struct wxScopedCharTypeBufferStreamSupport<char, Buffer>
|
||||
{
|
||||
#if wxUSE_STD_IOSTREAM
|
||||
friend std::ostream& operator<<(std::ostream& oss, const Buffer& buf)
|
||||
{
|
||||
return wxPrivate::OutputCharBuffer(oss, buf.data());
|
||||
}
|
||||
#endif // wxUSE_STD_IOSTREAM
|
||||
};
|
||||
|
||||
template <typename Buffer>
|
||||
struct wxScopedCharTypeBufferStreamSupport<wchar_t, Buffer>
|
||||
{
|
||||
#if wxUSE_STD_IOSTREAM
|
||||
friend std::ostream& operator<<(std::ostream& oss, const Buffer& buf)
|
||||
{
|
||||
return wxPrivate::OutputWCharBuffer(oss, buf.data());
|
||||
}
|
||||
#if defined(HAVE_WOSTREAM)
|
||||
friend std::wostream& operator<<(std::wostream& woss, const Buffer& buf)
|
||||
{
|
||||
return wxPrivate::OutputWCharBuffer(woss, buf.data());
|
||||
}
|
||||
#endif // defined(HAVE_WOSTREAM)
|
||||
#endif // wxUSE_STD_IOSTREAM
|
||||
};
|
||||
|
||||
wxGCC_ONLY_WARNING_RESTORE(non-template-friend)
|
||||
|
||||
|
||||
// Reference-counted character buffer for storing string data. The buffer
|
||||
// is only valid for as long as the "parent" object that provided the data
|
||||
// is valid; see wxCharTypeBuffer<T> for persistent variant.
|
||||
template <typename T>
|
||||
class wxScopedCharTypeBuffer
|
||||
: wxScopedCharTypeBufferStreamSupport<T, wxScopedCharTypeBuffer<T>>
|
||||
{
|
||||
public:
|
||||
typedef T CharType;
|
||||
|
|
@ -368,6 +428,13 @@ public:
|
|||
wxCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
|
||||
|
||||
wxCharBuffer(const wxCStrData& cstr);
|
||||
|
||||
#if wxUSE_STD_IOSTREAM
|
||||
// Define this to disambiguate between converting to the base class or to
|
||||
// wxString when using operator<<() with the objects of this class.
|
||||
friend WXDLLIMPEXP_BASE
|
||||
std::ostream& operator<<(std::ostream& oss, const wxCharBuffer& buf);
|
||||
#endif // wxUSE_STD_IOSTREAM
|
||||
};
|
||||
|
||||
class wxWCharBuffer : public wxCharTypeBuffer<wchar_t>
|
||||
|
|
@ -385,6 +452,16 @@ public:
|
|||
wxWCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
|
||||
|
||||
wxWCharBuffer(const wxCStrData& cstr);
|
||||
|
||||
#if wxUSE_STD_IOSTREAM
|
||||
// See wxCharBuffer for why this is needed.
|
||||
friend WXDLLIMPEXP_BASE
|
||||
std::ostream& operator<<(std::ostream& oss, const wxWCharBuffer& buf);
|
||||
#if defined(HAVE_WOSTREAM)
|
||||
friend WXDLLIMPEXP_BASE
|
||||
std::wostream& operator<<(std::wostream& woss, const wxWCharBuffer& buf);
|
||||
#endif // defined(HAVE_WOSTREAM)
|
||||
#endif // wxUSE_STD_IOSTREAM
|
||||
};
|
||||
|
||||
// wxCharTypeBuffer<T> implicitly convertible to T*, for char and wchar_t,
|
||||
|
|
|
|||
|
|
@ -291,6 +291,13 @@ public:
|
|||
return p - cs.AsWChar();
|
||||
}
|
||||
|
||||
#if wxUSE_STD_IOSTREAM
|
||||
friend WXDLLIMPEXP_BASE std::ostream& operator<<(std::ostream&, const wxCStrData&);
|
||||
#if defined(HAVE_WOSTREAM)
|
||||
friend WXDLLIMPEXP_BASE std::wostream& operator<<(std::wostream&, const wxCStrData&);
|
||||
#endif // defined(HAVE_WOSTREAM)
|
||||
#endif // wxUSE_STD_IOSTREAM
|
||||
|
||||
private:
|
||||
// the wxString this object was returned for
|
||||
const wxString *m_str;
|
||||
|
|
@ -3626,6 +3633,13 @@ public:
|
|||
wxString& operator+=(unsigned char ch) { return *this += wxUniChar(ch); }
|
||||
wxString& operator+=(wchar_t ch) { return *this += wxUniChar(ch); }
|
||||
|
||||
#if wxUSE_STD_IOSTREAM
|
||||
friend WXDLLIMPEXP_BASE std::ostream& operator<<(std::ostream&, const wxString&);
|
||||
#if defined(HAVE_WOSTREAM)
|
||||
friend WXDLLIMPEXP_BASE std::wostream& operator<<(std::wostream&, const wxString&);
|
||||
#endif // defined(HAVE_WOSTREAM)
|
||||
#endif // wxUSE_STD_IOSTREAM
|
||||
|
||||
private:
|
||||
#if !wxUSE_UTF8_LOCALE_ONLY
|
||||
int DoPrintfWchar(const wxChar *format, ...);
|
||||
|
|
@ -4158,27 +4172,6 @@ namespace std
|
|||
// Implementation only from here until the end of file
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#if wxUSE_STD_IOSTREAM
|
||||
|
||||
#include "wx/iosfwrap.h"
|
||||
|
||||
WXDLLIMPEXP_BASE std::ostream& operator<<(std::ostream&, const wxString&);
|
||||
WXDLLIMPEXP_BASE std::ostream& operator<<(std::ostream&, const wxCStrData&);
|
||||
#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
|
||||
WXDLLIMPEXP_BASE std::ostream& operator<<(std::ostream&, const wxScopedCharBuffer&);
|
||||
#endif // wxNO_IMPLICIT_WXSTRING_ENCODING
|
||||
WXDLLIMPEXP_BASE std::ostream& operator<<(std::ostream&, const wxScopedWCharBuffer&);
|
||||
|
||||
#if defined(HAVE_WOSTREAM)
|
||||
|
||||
WXDLLIMPEXP_BASE std::wostream& operator<<(std::wostream&, const wxString&);
|
||||
WXDLLIMPEXP_BASE std::wostream& operator<<(std::wostream&, const wxCStrData&);
|
||||
WXDLLIMPEXP_BASE std::wostream& operator<<(std::wostream&, const wxScopedWCharBuffer&);
|
||||
|
||||
#endif // defined(HAVE_WOSTREAM)
|
||||
|
||||
#endif // wxUSE_STD_IOSTREAM
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// wxCStrData implementation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -169,17 +169,29 @@ std::ostream& operator<<(std::ostream& os, const wxString& str)
|
|||
return os << str.c_str();
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const wxScopedCharBuffer& str)
|
||||
std::ostream&
|
||||
wxPrivate::OutputCharBuffer(std::ostream& os, const char* str)
|
||||
{
|
||||
return os << str;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const wxCharBuffer& str)
|
||||
{
|
||||
return os << str.data();
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const wxScopedWCharBuffer& str)
|
||||
std::ostream&
|
||||
wxPrivate::OutputWCharBuffer(std::ostream& os, const wchar_t* wstr)
|
||||
{
|
||||
// There is no way to write wide character data to std::ostream directly,
|
||||
// but we need to define this operator for compatibility, as we provided it
|
||||
// since basically always, even if it never worked correctly before. So do
|
||||
// the only reasonable thing and output it as UTF-8.
|
||||
return os << wxConvWhateverWorks.cWC2MB(wstr);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const wxWCharBuffer& str)
|
||||
{
|
||||
return os << wxConvWhateverWorks.cWC2MB(str.data());
|
||||
}
|
||||
|
||||
|
|
@ -195,7 +207,13 @@ std::wostream& operator<<(std::wostream& wos, const wxCStrData& str)
|
|||
return wos << str.AsWChar();
|
||||
}
|
||||
|
||||
std::wostream& operator<<(std::wostream& wos, const wxScopedWCharBuffer& str)
|
||||
std::wostream&
|
||||
wxPrivate::OutputWCharBuffer(std::wostream& wos, const wchar_t* wstr)
|
||||
{
|
||||
return wos << wstr;
|
||||
}
|
||||
|
||||
std::wostream& operator<<(std::wostream& wos, const wxWCharBuffer& str)
|
||||
{
|
||||
return wos << str.data();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue