std::source_location is Broken

Everyone knows that the best way to get something done on the Internet is with an inflammatory title and a potentially incorrect contention, so here goes.

What do you if you want to capture/log the filename of an assertion? Prior to C++20, you use good old __FILE__, which gives you a C-style array of chars. But of course this is a macro, and means that your logging/assertion code has to be a macro. With all the usual downsides of macros. Ho hum, that’s how it is for now, and it works. You go on your way.

After upgrading to C++20, you wonder if you can upgrade your logging/assertion code to use std::source_location. Then maybe you could get rid of the macros. It looks odd at first, because you have to set it up as a default argument to your log function. But hey, this was someone’s clever solution to the problem, right? Obviously arguments are supplied at the call site, and default arguments are arguments, so they are too. So the std::source_location default argument picks up the location of the call site, and you can grab the file_name from it as a const char*.

But… now it doesn’t work. Because that’s not how your logging works. You’re working in embedded. No room for strings in your binary. Instead, you model your (statically-known) strings as types like string_constant<'H', 'e', 'l', 'l', 'o'>, you use nm to extract the symbols from your library, and you generate tiny function specializations which turn the types into numbers, and melt away with LTO. (Like this.)

You need strings to be types. You need to know the size at compile time. std::source_location::file_name() gives you a const char* – you don’t know the size of the string. And because it has to be a function argument, it can’t be constexpr. There is no way to get back into type land. (At least, none that I know of yet, and believe me, I’ve tried. If you know how, let me know!) It’s the same story for the intrinsics that std::source_location is built upon (__builtin_FILE_NAME).

So you sadly accept that until and unless you get jam tomorrow another mechanism to do this, be it constexpr function arguments or whatever, you’re stuck with __FILE__, which works, because it gives you a sized char array which you can turn into a type.

Of course the irony here is that std::source_location provides information that is known only at compile time. But we can’t use that information fully at compile time, because it’s inadequately specified/implemented.

Categorized as C++