我有一個constexpr函式,我試圖從__FILE__宏中洗掉檔案名,也就是說,洗掉除路徑之外的所有內容。為此,我草擬了這個基本函式,并constexpr希望編譯器能夠推斷出結果并將計算結果作為字串放入最終的二進制檔案中。該功能并不完美,只是一個簡單的模型。
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;
}
問題是這沒有在編譯時進行評估(構建:MSVC x64 Release Maximum Speed optimization)。我假設這是因為回傳一個指向二進制常量字串內的指標,這本質上是函式正在做的事情。但是,我希望編譯器做的是決議get_filename函式并以某種方式回傳字串字面"main.cpp"量,例如,而不是回傳該子字串的指標。本質上,我希望它編譯下來,以便最終的二進制檔案包含main.cpp在其中,而沒有其他__FILE__宏的一部分。這可能嗎?
uj5u.com熱心網友回復:
因為您不想要__FILE__最終二進制檔案中的完整路徑,所以我們必須將字串復制到 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;
}
并constexpr在呼叫get_filename函式時指定:
constexpr auto fileName = get_filename();
std::cout << fileName.data();
或者,從 C 20 開始,您可以使用consteval它來強制在編譯時對其進行評估:
consteval auto get_filename();
這是對 godbolt 的測驗,它使用printf而不是std::cout更短的 asm。
uj5u.com熱心網友回復:
像這樣,我的代碼位于一個名為 .\some_path\main.cpp 的檔案中(Windows 路徑樣式):
#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;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/522376.html
下一篇:C 將物件族傳遞給類
