{"id":1738,"date":"2023-11-16T09:16:49","date_gmt":"2023-11-16T16:16:49","guid":{"rendered":"https:\/\/www.elbeno.com\/blog\/?p=1738"},"modified":"2023-11-16T09:34:44","modified_gmt":"2023-11-16T16:34:44","slug":"stdsource_location-is-broken","status":"publish","type":"post","link":"https:\/\/www.elbeno.com\/blog\/?p=1738","title":{"rendered":"std::source_location is Broken"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">What do you if you want to capture\/log the filename of an assertion? Prior to C++20, you use good old <code>__FILE__<\/code>, which gives you a C-style array of <code>char<\/code>s. 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&#8217;s how it is for now, and it works. You go on your way.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After upgrading to C++20, you wonder if you can upgrade your logging\/assertion code to use <code>std::source_location<\/code>. 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&#8217;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 <code>std::source_location<\/code> default argument picks up the location of the call site, and you can grab the <code>file_name<\/code> from it as a <code>const char*<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"> But&#8230; now it doesn&#8217;t work. Because that&#8217;s not how your logging works. You&#8217;re working in embedded. No room for strings in your binary. Instead, you model your (statically-known) strings as types like <code>string_constant&lt;'H', 'e', 'l', 'l', 'o'&gt;<\/code>, you use <code>nm<\/code> to extract the symbols from your library, and you generate tiny function specializations which turn the types into numbers, and melt away with LTO. (<a href=\"https:\/\/www.youtube.com\/watch?v=Dt0vx-7e_B0\">Like this.<\/a>)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You need strings to be types. You need to know the size at compile time. <code>std::source_location::file_name()<\/code> gives you a <code>const char*<\/code> &#8211; you don&#8217;t know the size of the string. And because it has to be a function argument, it can&#8217;t be <code>constexpr<\/code>. There is no way to get back into type land. (At least, none that I know of yet, and believe me, I&#8217;ve tried. If you know how, let me know!) It&#8217;s the same story for the intrinsics that <code>std::source_location<\/code> is built upon (<code>__builtin_FILE_NAME<\/code>).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So you sadly accept that until and unless you get <s>jam tomorrow<\/s> another mechanism to do this, be it <code>constexpr<\/code> function arguments or whatever, you&#8217;re stuck with <code>__FILE__<\/code>, which works, because it gives you a <em>sized<\/em> <code>char<\/code> array which you <em>can<\/em> turn into a type.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Of course the irony here is that <code>std::source_location<\/code> provides information that is known <em>only<\/em> at compile time. But we can&#8217;t <em>use<\/em> that information fully at compile time, because it&#8217;s inadequately specified\/implemented.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&#8230;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22],"tags":[],"class_list":["post-1738","post","type-post","status-publish","format-standard","hentry","category-cpp"],"_links":{"self":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1738","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1738"}],"version-history":[{"count":2,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1738\/revisions"}],"predecessor-version":[{"id":1740,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1738\/revisions\/1740"}],"wp:attachment":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1738"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1738"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1738"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}