One of the issues I have had in porting some stuff from Solaris to Linux is that the Solaris compiler expands the macro __FILE__
during preprocessing to the file name (e.g. MyFile.cpp) whereas gcc on Linux expandeds out to the full path (e.g. /home/user/MyFile.cpp). This can be reasonably easily resolved using basename() but....if you're using it a lot, then all those calls to basename() have got to add up, right?
Here's the question. Is there a way using templates and static metaprogramming, to run basename() or similar at compile time? Since __FILE__
is constant and known at compile time this might make it easier. What do you think? Can it be done?
Using C++11, you have a couple of options. Let's first define:
If your compiler supports statement expressions, and you want to be sure that the basename computation is being done at compile-time, you can do this:
If your compiler doesn't support statement expressions, you can use this version:
With this non stmt-expr version, gcc 4.7 and 4.8 call basename_index at run-time, so you're better off using the stmt-expr version with gcc. ICC 14 produces optimal code for both versions. ICC13 can't compile the stmt-expr version, and produces suboptimal code for the non stmt-expr version.
Just for completeness, here's the code all in one place:
Another C++11
constexpr
method is as follows:The usage is pretty simple also:
The
constexpr
will be performed at compile-time if possible, otherwise it will fallback to run-time execution of the statements.The algorithm is a little different in that it finds the end of the string and then works backwards to find the last slash. It is probably slower than the other answer but since it is intended to be executed at compile-time it shouldn't be an issue.