I want to convert std::uint16_t to std::string_view. I was expecting the following code would work:
std::string_view to_str(std::uint16_t v) {
return std::string_view(std::to_string(v));
}
because it uses an intermediary std::string in to_str function scope.
I know I can use a static storage for intermediary string like this:
std::string_view to_str(std::uint16_t v) {
static auto str = std::to_string(v);
return std::string_view(str);
}
I know there is another way to use char buffer and convert it to string_view but I wonder is there any better way to serve this very same purpose? Is it even logical to return string_view instead of string?
The problem is that std::string_view is a lightweight class that does not own the data. It is marely a view into the data held by another object (e.g. a std::string). And you need the object holding the data to be alive as long as you intend to use the string_view.
In this line:
return std::string_view(std::to_string(v));
You return a string_view referring a temporary std::string returned from std::to_string. This temporary is then destroyed and therefore the string_view that you return is invalid (similarly to a dangling pointer/reference). Accessing it invokes undefined-behavior.
When you use static auto str = std::to_string(v); it seems to solve this problem because the static str will stay alive after the function returns. But in fact it is not a good solution. str will only be initialize once and so the next call to to_str with a different value for v will still return a string_view for the first call.
The solution is to simply return a std::string instead of a std::string_view (returning a string_view does not make sense because of the reason explained above).
You will still be able to pass it to methods that expect a std::string_view.