bpeikes
bpeikes

Reputation: 3715

c++20 handling of string literals

We’re updating a project to c++20, and are running into errors where we pass string literals into functions which take char *. I know this has been changed to make code more safe, but we are interfacing with libraries which we cannot change.

I’d rather not disable the strict treatment of literals via compiler flags, so is there a good way to wrap these literals just in these particular cases?

I was thinking of an inline function, that was named something specific to the library, that internally would use const_cast. That way later if we want to change the code because the library gets updated, we know exactly where to look.

Any other ideas?

Upvotes: 1

Views: 1742

Answers (2)

Taekahn
Taekahn

Reputation: 1717

"Any other ideas?"

static char my_string[] = "string";
... 
//elsewhere in the code
library_function(my_string);

The only difference between passing a string like that, and passing a string literal is the section of the assembly the data is stored in.
A string literal is stored in .text, a non-modifiable section.
The non-const string will be stored in .data.

If you really, really care if you're passing a function a pointer to .text or a pointer to .data, and you really, really, trust the library to not modify the parameter now and for ever, then you can certainly cast away the const-ness of your string literals.

Ignoring the fact that documentation lags behind implementation, even if we could believe the documentation promise to not modify its inputs, if it doesn't enforce it through the interface, at any time, on purpose or on accident, that input could be modified.

Upvotes: 1

Sebastian
Sebastian

Reputation: 1974

The following string literal creates a std::string for each literal and implicitly converts to char*.

#include <string>
    
struct stringlitwrapper
{
    constexpr stringlitwrapper(const char* c) : s(c) {};
    operator char*() { return s.data(); }
    std::string s;
};

constexpr stringlitwrapper operator"" _w (const char* c, std::size_t n)
{
    return stringlitwrapper(c);
}


void libfunction(char* param) {
    // uses non-const char* as parameter
}

int main() {
    libfunction("string literal"_w);
    return 0;
}

For compilers, which do not support constexpr here (e.g. msvc does, clang not), leave both constexpr away.

By internally storing the literal as non-const string, there is no undefined behaviour involved.

(The library function of course should not overwrite at all or at least not write over the end of the string.)

To prevent heap allocations, the std::string could be replaced by a char array with fixed (maximal) size.

Upvotes: 0

Related Questions