I'm not a huge fan of C++'s std::basic_string class template.
It lacks some common routines found in many modern languages' class library string implementation. It's also a mutable string, which makes it more complex and you end up with more code bloat. There's no first-class UTF-8 or UTF8-16 support either. The meaning of wchar_t and the L string prefix vary by platform. On Windows, it maps to UCS-2, an ancestor of UTF-16. On Linux, it maps to UTF-32.
At my last place of work, we ended up rolling our own C++ string templates. We created encoding classes which captured a lot of the common traits and functions. And then we made the string template be parameterizable on an encoding class type. Our string implementation was also immutable, thread-safe reference-counted, and had modern-style operations. It also came with a string_builder class for mutable operations and you customize it to use whatever container on the backend--it was set to std::deque by default.
So we had:
class string_encoding; // ascii
class wstring_encoding; // wchar_t
class u8string_encoding; // utf8
class u16string_encoding; // utf16
class u32string_encoding; // utf32
template< class Encoding, class Allocator >
class generic_string;
template< class Encoding, class Container >
class generic_string_builder;