Fix using std::reverse() with wxString iterators in a proper way
The solution with specializing std::iter_swap() for wxString::iterator was not conforming as the iterator was still not swappable, as it is required to be. Fix this by providing std::swap() overload for wxString::iterator, which is correct and even simpler. This allows std::reverse(s.begin(), s.end()) work with clang too and incidentally avoids warnings about the code relying on non-conforming extensions with MSVS 2017 which were due to the fact that iter_swap() workaround wasn't enabled for it, while the new swap() overload is.
This commit is contained in:
@@ -3980,32 +3980,6 @@ namespace std
|
|||||||
|
|
||||||
#endif // C++11
|
#endif // C++11
|
||||||
|
|
||||||
// Specialize std::iter_swap in C++11 to make std::reverse() work with wxString
|
|
||||||
// iterators: unlike in C++98, where iter_swap() is required to deal with the
|
|
||||||
// iterator::reference being different from "iterator::value_type&", in C++11
|
|
||||||
// iter_swap() just calls swap() by default and this doesn't work for us as
|
|
||||||
// wxUniCharRef is not the same as "wxUniChar&".
|
|
||||||
//
|
|
||||||
// Unfortunately currently iter_swap() can't be specialized when using libc++,
|
|
||||||
// see https://llvm.org/bugs/show_bug.cgi?id=28559
|
|
||||||
#if (__cplusplus >= 201103L) && !defined(_LIBCPP_VERSION)
|
|
||||||
|
|
||||||
namespace std
|
|
||||||
{
|
|
||||||
template <>
|
|
||||||
inline void
|
|
||||||
iter_swap<wxString::iterator>(wxString::iterator i1, wxString::iterator i2)
|
|
||||||
{
|
|
||||||
// We don't check for i1 == i2, this won't happen in normal use, so
|
|
||||||
// don't pessimize the common code to account for it.
|
|
||||||
wxUniChar tmp = *i1;
|
|
||||||
*i1 = *i2;
|
|
||||||
*i2 = tmp;
|
|
||||||
}
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
#endif // C++11
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Implementation only from here until the end of file
|
// Implementation only from here until the end of file
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@@ -360,6 +360,23 @@ void swap<wxUniCharRef>(wxUniCharRef& lhs, wxUniCharRef& rhs)
|
|||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
|
#if __cplusplus >= 201103L || wxCHECK_VISUALC_VERSION(10)
|
||||||
|
|
||||||
|
// For std::iter_swap() to work with wxString::iterator, which uses
|
||||||
|
// wxUniCharRef as its reference type, we need to ensure that swap() works with
|
||||||
|
// wxUniCharRef objects by defining this overload.
|
||||||
|
//
|
||||||
|
// See https://bugs.llvm.org/show_bug.cgi?id=28559#c9
|
||||||
|
inline
|
||||||
|
void swap(wxUniCharRef&& lhs, wxUniCharRef&& rhs)
|
||||||
|
{
|
||||||
|
wxUniChar tmp = lhs;
|
||||||
|
lhs = rhs;
|
||||||
|
rhs = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // C++11
|
||||||
|
|
||||||
|
|
||||||
// Comparison operators for the case when wxUniChar(Ref) is the second operand
|
// Comparison operators for the case when wxUniChar(Ref) is the second operand
|
||||||
// implemented in terms of member comparison functions
|
// implemented in terms of member comparison functions
|
||||||
|
@@ -626,13 +626,7 @@ void StdStringTestCase::StdConversion()
|
|||||||
|
|
||||||
void StdStringTestCase::StdAlgo()
|
void StdStringTestCase::StdAlgo()
|
||||||
{
|
{
|
||||||
// Unfortunately this currently doesn't work with libc++ in C++11 mode, see
|
|
||||||
// comment near iter_swap() definition in wx/string.h.
|
|
||||||
#if __cplusplus < 201103L || !defined(_LIBCPP_VERSION)
|
|
||||||
wxString s("AB");
|
wxString s("AB");
|
||||||
std::reverse(s.begin(), s.end());
|
std::reverse(s.begin(), s.end());
|
||||||
CPPUNIT_ASSERT_EQUAL( "BA", s );
|
CPPUNIT_ASSERT_EQUAL( "BA", s );
|
||||||
#else
|
|
||||||
wxLogWarning("Skipping std::reverse() test broken with C++11/libc++");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user