Consider the following code:
void Log(std::string_view msg,
std::source_location const& loc = std::source_location::current()) {
// Performance penalty!
auto const n = std::strlen(loc.file_name());
auto s = ""s;
s.resize(msg.size() + n);
std::memcpy(&s[0], msg.data(), msg.size());
std::memcpy(&s[msg.size()], loc.file_name(), n);
// sendToRemoteMachine(s);
}
Obviously, if std::source_location::file_name
returns a std::string_view
, the performance penalty can be easily avoided.
I think, std::source_location::file_name
is a compile-time generated and readonly information. The compiler can store it into an std::string_view
object.
Why doesn't std::source_location
provide lengths to avoid performance penalty in C++20?
Update
Another related article: std::source_location
is Broken
C++ does not have a type that represents all of the following:
std::string
has both 2 and 3, but not 1. string_view
has 1 and 2, but does not guarantee 3 at the type level. char const*
has 1 and there's a general expectation that they use 3, but they don't carry 2.
And yes, #3 is actually quite important. Your example wants to pass the string to an API that needs a sized string; that's why you're computing the size. Other people will have APIs that expect an NTBS. For them, a string_view
-based API now requires that they copy the sized-string into an NTBS. Which is an O(N) operation.
Unless you have a type that communicates all 3 of these, one of you is going to have to do an O(N) operation.
Yes, technically, a string_view
could point to an NTBS. But at the type level, if you're handed a string_view
, you don't know that it points to an NTBS. That would be a guarantee from the function that generates it, not from the type itself. So it would be an inappropriate use of the type.
Another related article
This article is about a largely separate issue: the lack of a constexpr
version of source_location
, one which would allow the string to be guaranteed to only exist at compile-time.
This issue is not something that any library construct could ever solve. Returning string_view
from member functions wouldn't fix the problem from that article. While string_view
can be constexpr
, parameters cannot. And since source_location
is passed as a parameter, it must follow the rules of the C++ language. Even though the compiler generated it, it is a parameter of the function and therefore it cannot be a constexpr
parameter.
Indeed, it couldn't even be a C++ language construct because the language cannot pass compile-time information as a function parameter. Remember: the source of the information is the caller. What the writer of that article would do with __FILE__
is manually stick it into a template parameter of that function, not a function parameter.
And it should be noted: returning a size isn't the problem as outlined by the article. You can compute a size of a char const*
at compile-time, if the char const*
itself is constexpr
. You can then use that compile-time size and the char const*
itself to manufacture a type. The problem the article is talking about is entirely in the scope of getting a compile-time sequence of characters. Whether it's a string_view
or a char const*
NTBS or a char[N]
is irrelevant; any of them would work.