Opened 2 years ago

Closed 17 months ago

Last modified 4 months ago

#14694 closed defect (fixed)

Document the unexpected behaviour of wxString::operator[] with templates/auto

Reported by: pmgrace30 Owned by:
Priority: normal Milestone: 3.0.0
Component: documentation Version: 2.9.4
Keywords: wxString template wxUniCharRef difficult Cc:
Blocked By: Blocking:
Patch: no

Description

Unexpected behaviour using wxString with templates
I recently tried out wxString with some STL utilities. Some things worked and others did not. I isolated one of the problems to unexpected behaviour when used with templates. The example below uses a simple swap template (myswap) to swap two characters in a wxString. The output from the program is shown below and it is clearly not swapping. The same problem occurs if I replace myswap with std::swap. The comments in myswap show what is happening.
template<class T> inline void myswap(T& lhs, T& rhs)
{

T tmp = lhs; T is wxUniCharRef (which behaves like a reference)
lhs = rhs;
tmp also changes to equal rhs
rhs = tmp;

}

int main()
{

cout << "test swap using []\n" << s1 << endl;
wxString s1("ab");
myswap(s1[0], s1[1]);
cout << s1 << endl;


cout << "test swap using iterators\n" << s2 << endl;
wxString s2("ab");
auto t0 = s2.begin();
auto t1 = t0 + 1;
myswap(*t0, *t1);
cout << s2 << endl;

}
OUTPUT
test swap using []
ab
bb
test swap using iterators
ab
bb

Change History (6)

comment:1 Changed 2 years ago by pmgrace30

Sorry
The main function should read

int main()
{

wxString s1("ab");
cout << "test swap using []\n" << s1 << endl;
myswap(s1[0], s1[1]);
cout << s1 << endl;


wxString s2("ab");
cout << "test swap using iterators\n" << s2 << endl;
auto t0 = s2.begin();
auto t1 = t0 + 1;
myswap(*t0, *t1);
cout << s2 << endl;

}

comment:2 Changed 2 years ago by vadz

  • Keywords difficult added
  • Status changed from new to confirmed
  • Summary changed from Unexpected behaviour using wxString with templates to Unexpected behaviour using wxString::operator[] with templates

I see the problem and agree it is, indeed, a problem, but I don't see what can we do about it. wxString::operator[] must return wxUniCharRef to allow modification of the string via it and so the type of s[n] is wxUniCharRef and not the more expected wxUniChar. std::basic_string has it easy as it just returns a real reference which is discarded when using the template function but we can't do this because we can't allow writing directly into wxString buffer. So I just don't see any solution to this, unfortunately.

comment:3 Changed 2 years ago by pmgrace30

The use of auto with wxString characters is showing the same problem. See below. I think this makes it more serious as auto is likely to be used much more than templates.

int main()
{

cout << "test auto\n";
wxString s("a");
auto x = s[0];
cout << "s = " << s << " x = " << x << endl;
s[0] = 'z';
cout << "s = " << s << " x = " << x << endl;
return 0;

}
OUTPUT
test auto
s = a x = a
s = z x = z

comment:4 Changed 2 years ago by vadz

  • Component changed from wxMSW to documentation
  • Milestone set to 3.0
  • Summary changed from Unexpected behaviour using wxString::operator[] with templates to Document the unexpected behaviour of wxString::operator[] with templates/auto

Yes, it's indeed even more serious. Unfortunately this still doesn't change the fact that I have absolutely no idea about what could we do about it :-(

We do need to document this "reference semantics" of s[n] but apart from this I just don't see anything.

comment:5 Changed 17 months ago by VZ

  • Resolution set to fixed
  • Status changed from confirmed to closed

(In [73905]) Expand wxString overview and document some problems due to its dual nature.

Explain the possible problems with wxString due to its dual Unicode/ASCII
nature.

Also document the various conversions in the overview itself.

Closes #14694.

comment:6 Changed 4 months ago by VZ

In 76474:

Define std::swap() correctly for wxUniCharRef.

The default implementation doesn't work for this reference-like class, and
this breaks not only swap() itself (see #14694), but also any algorithms using
it, such as std::reverse().

Fix this by providing our own specialization which does work correctly.

Closes #16234.

Note: See TracTickets for help on using tickets.