I have a constexpr
function and I'm trying to strip the file name from the __FILE__
macro, that is, remove everything but the path. I sketched up this basic function to do so, and I made it constexpr
in hopes that the compiler can deduce the result and just place that calculated result as a string in the final binary. The function isn't perfect, just a simple mock-up.
constexpr const char* const get_filename()
{
auto file{ __FILE__ };
auto count{ sizeof(__FILE__) - 2 };
while (file[count - 1] != '\\')
--count;
return &file[count];
}
int main()
{
std::cout << get_filename() << std::endl;
return 0;
}
The problem is that this is not being evaluated at compile time (build: MSVC x64 Release Maximum Speed optimization). I'm assuming this is because of returning a pointer to something inside a constant string in the binary, which is essentially what the function is doing. However, what I want the compiler to do is parse the get_filename
function and somehow return the string literal "main.cpp"
, for example, instead of returning a pointer of that substring. Essentially, I want this to compile down so that the final binary just has main.cpp
in it, and nothing else part of the __FILE__
macro. Is this possible?
CodePudding user response:
Because you don't want the full __FILE__
path in the final binary, we must copy the string to a std::array
:
constexpr auto get_filename()
{
constexpr std::string_view filePath = __FILE__;
constexpr auto count = filePath.rfind("\\");
static_assert(count != std::string::npos);
std::array<char, count> fileName{};
std::copy(filePath.data() count 1, filePath.data() filePath.size(), fileName.data());
return fileName;
}
And specify constexpr
when calling the get_filename
function:
constexpr auto fileName = get_filename();
std::cout << fileName.data();
Alternatively, since C 20, you could use consteval
to force it to be evaluated at compile time:
consteval auto get_filename();
Here's the test on godbolt, it uses printf
instead of std::cout
for a shorter asm.
CodePudding user response:
Like this my code is in a file called .\some_path\main.cpp (windows path style):
#include <string_view>
#include <iostream>
static constexpr std::string_view get_filename()
{
std::string_view name{ __FILE__ };
auto pos = name.find_last_of('\\'); // or '/' on linux
if (pos != std::string::npos)
{
return std::string_view{ name.begin() pos 1, name.end() };
}
return name;
}
int main()
{
static_assert(get_filename() == "main.cpp");
std::cout << get_filename();
return 0;
}