The IME gets a lot of hate around here, but let's not get distracted by it: higher-privilege co-processors running code outside the main OS' control is becoming (or already is) the norm everywhere. Intel-based PCs are just one instance of it (and perhaps not even the most egregious one).
Most hardware has evolved to effectively run the main OS under a sandbox where it "thinks" it is in control, but isn't.
Python only because it's the string class that I've used that always has everything I need. QString from Qt is pretty good, too. std::string is, like you say, painful. Since QString exists, works great with a long history, so why is std::string so limited? Design-wise, I'd say the few changes which QString has had demonstrates the solidity of the design.
Off the top of my head, what I use frequently (and which is unavailable in std::String) is:
- replace(search, new). std::string can do it, but first you have to find the index of the start, then you call replace() to replace a set of bytes. Too low level.
- endswith() and beginswith() are surprisingly helpful. endswith() in particular. s.index("prefix") == 0 is pretty clear, but s.index("suffix") == s.size() - "suffix".size() is not very clear.
- toupper()/tolower()/isspace()/isslanum()/isupper()/etc. are not something you use every day, but you really don't want to have to write proper handling of every language's idiosyncracies yourself, and it's not worth it to find a library, so probably only European languages will work initially.
- proper unicode handling. std::wstring (UTF16) is not it (to be fair, that wasn't clear at the time of design), plus I don't think it works well with either Microsoft's or Apple's UTF16
- making a string from a number. QString does this well, Python 2's str(num) is not really flexible enough. I don't want to have to create a stringstream just because I need a numeric string.
- create a string from a printf list. I know stringstream is supposed to do that, but I never seem to be able to do exactly what I want (e.g. %.3f), and regardless, I never can remember the correct syntax for the modifiers (e.g. hex(), precision()), despite it appearing like it ought to be obvious.
I pretty much expect all the above in a string. std::string is basically a veneer over an array of bytes. Maybe that was okay in 1998 when it was designed, but the first thing I have to do is add all that in now, every time I do anything UI-related with text.
I also would like split(), it makes simple parsing a lot easier.
Most hardware has evolved to effectively run the main OS under a sandbox where it "thinks" it is in control, but isn't.
A nice talk on this: https://www.youtube.com/watch?v=36myc8wQhLo