Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any gotchas replacing global const char[] with constexpr string_view?

Our team is working with a 10+ years old C++ code base and recently switched to a C++17 compiler. So we are looking for ways to modernize our code. In a conference talk on YouTube I heard the suggestion, to replace const char* global strings with constexpr string_view.

Since we got quite a number of such const char* global string constants in our code, I want to ask if there are any gotchas or potential issues we need to be aware of?

like image 517
PixelSupreme Avatar asked Oct 08 '19 07:10

PixelSupreme


1 Answers

These issues might be worth being aware of:

  1. std::string_view doesn't need to be null-terminated. So if you replace some const char* by string_view and replace the construction of a previously null-terminated char* substring by a string_view via std::string_view::substr, you can't pass the underlying pointer to an API that expects a null-terminated string. Example (without UB, but that is easily constructable, too):

    void legacy(const char *str) {
       std::printf("%s\n", str);
    }
    
    constexpr std::string_view sv1 = "abcde";
    constexpr std::string_view sv2 = sv1.substr(0, 2); // view on "ab"
    
    legacy(sv2.data()); // Not intended: prints "abcde" 
    
  2. While you can implicitly construct a std::string from a const char*, you cannot do that with a std::string_view. The idea is that a deep copy shouldn't happen under the cover, but only when explicitly requested. Example:

    std::map<std::string, int> m;
    constexpr std::string_view sv = "somekey";
    constexpr const char *old = "somekey";
    
    m[old] = 42; // works as expected
    m[sv] = 42; // fails to compile
    m[std::string(sv)] = 42; // be explicit, this is ok
    

    Depending on the existing usage of the global const char* instances in your project, this behavior might require manual intervention at various places.

like image 106
lubgr Avatar answered Oct 20 '22 22:10

lubgr