0

I have a C++ app with deep, refined logic developed over many years. Sadly, it combines all manner of different types of strings: std::string, C-strings, Pascal strings, and OS/platform-specific strings. Plus, each of these string types often use various encodings.

I've created a wrapper class, WBString, that holds an std::string, and can construct from nearly a dozen types of my pre-existing strings.

However, I'd like the underlying implementation to be able to use std::string_view. If I'm constructing from a source string that's already const, an std::string_view could save all manner of behind-the-scenes construction when initializing and passing my class around.

It SEEMS as if C++17's std::string_view could have simply attempted a better integration with std::string, but I guess that could break existing apps.

I could see numerous ways of doing this:

1) Templatizing my WBString class to hold an std::string for non-const functions and a separate WBStringView for const strings;

2) Create a base class with no data and two separate inherited classes: WBString / WBStringView;

3) Have a single class that incorporates BOTH std::string and std::string_view as data members;

4) Keep a single void* data member which could be either type.

Anyone had to confront this issue before?

SMGreenfield
  • 1,680
  • 19
  • 35
  • 6
    Something like `std::variant` ? – KamilCuk Jun 18 '19 at 23:34
  • 6
    _"If I'm constructing from a source string that's already const"_ How will you know whether that const string's lifetime will be longer than the `string_view`, so that the `string_view` doesn't end up referring to freed memory? – Jonathan Wakely Jun 18 '19 at 23:35
  • @JonathanWakely -- Since all of the strings in question are PRESENTLY being used to construct things like const std::string&, or const char* (or other types expected to unmutable const), then they were expected to live the lifetime of the scope, or they were allocated as objects using new (or even malloc), so those cases I'd have to be more careful. – SMGreenfield Jun 18 '19 at 23:50
  • 2
    Ok, so you know at construction time whether to make a copy, or use a view. In that case I think using a variant as suggested above makes sense. Use that internally and add a consistent string-like API over the top, accessing the active member of the variant. – Jonathan Wakely Jun 19 '19 at 00:01
  • @JonathanWakely - And -- if anything in my string_view variant call chain needs an actual std::string (or even a const std::string&), then I have to, at that time, actually CONSTRUCT a true std::string, right? string_view can't be passed in place of a const std::string&, right? – SMGreenfield Jun 19 '19 at 00:13
  • 2
    @SMGreenfield: "*they were expected to live the lifetime of the scope*" But you have absolutely no enforcement mechanism for that, since your current string type is just a wrapper around `std::string`. So you have no idea how much of your code violates this "expectation". A violation which worked previously, but in your new version will break the world. Essentially, this is 50% of the reason *why* `std::string` does not do things this way. – Nicol Bolas Jun 19 '19 at 00:15
  • That's correct. – Jonathan Wakely Jun 19 '19 at 00:15
  • @NicolBolas -- My "current string" isn't a wrapper at all -- it's like 8 different legacy string types. For example, in the MacOS version, which was built with Metrowerks PowerPlant, there's LString / LStr255. There's also Str255 (a Pascal-type string array of 255 chars), and char arrays, and const char*, as well as CFString and NSString and of course, good old std::string. So in if those were stack allocations, then so would my wrapper-based string_view. – SMGreenfield Jun 19 '19 at 00:24

0 Answers0