[英]How to get filename from __FILE__ and concat with __LINE__ at compile time
我試圖在編譯時連接文件名和沒有路徑的行。 像/tmp/main.cpp20
-> main.cpp:20
#include <array>
#include <iostream>
using namespace std;
#define STRINGIZE(x) STRINGIZE2(x)
#define STRINGIZE2(x) #x
#define LINE_STRING STRINGIZE(__LINE__)
constexpr const char* file_name(const char* path) {
const char* file = path;
while (*path) {
if (*path++ == '/') {
file = path;
}
}
return file;
}
constexpr std::size_t str_size(const char* str) {
auto i = str;
while (*i != '\0') ++i;
const auto length = i - str;
return length;
}
template <std::size_t N1, std::size_t N2>
constexpr std::array<char, N1 + N2 + 2> formatFilename(const char* name,
const char* line) {
auto total_size = N1 + N2 + 2;
std::array<char, N1 + N2 + 2> res{};
std::size_t i = 0;
for (; i < N1; ++i) {
res[i] = name[i];
}
res[i++] = ':';
for (int j = 0; j < N2; ++j) {
res[i + j] = line[j];
}
res[total_size - 1] = '\0';
return res;
}
int main() {
constexpr char *p = &(
formatFilename<str_size(file_name(__FILE__)), str_size(LINE_STRING)>(
file_name(__FILE__), LINE_STRING)[0]);
cout << p << endl;
}
但它似乎不起作用並返回編譯錯誤
main.cpp:在函數'int main()'中:main.cpp:46:46:錯誤:調用非'constexpr'函數'std::array<_Tp,_Nm>::value_type& std::array<_Tp , _Nm>::operator[](std::array<_Tp, _Nm>::size_type) [with _Tp = char; long unsigned int _Nm = 12; std::array<_Tp, _Nm>::reference = char&; std::array<_Tp, _Nm>::value_type = char; std::array<_Tp, _Nm>::size_type = long unsigned int]'
有沒有辦法在編譯時做到這一點?
對於您的特定情況(獲取沒有路徑和行號的文件名),您可能想要使用一些更簡單的方法:
__FILE_NAME__
代替__FILE__
gcc 和 clang 都支持__FILE_NAME__
宏,它只是解析為文件名而不是完整的文件路徑。
利用那些你可以把它寫成一個宏:
#define STRINGIFY(x) STRINGIFY_IMPL(x)
#define STRINGIFY_IMPL(x) #x
#define FILENAME __FILE_NAME__ ":" STRINGIFY(__LINE__)
// Usage:
constexpr char* foo = FILENAME;
std::cout << foo << std::endl;
不幸的是,msvc 不提供__FILE_NAME__
宏,但您可以使用/FC
編譯器開關來指定您是否需要__FILE__
的完整路徑或只是文件名。
--
相鄰的字符序列由編譯器自動組合- 例如"a" "b" "c"
將組合成"abc"
。
您可以使用它讓編譯器為您進行連接。
之后,我們可以將指向該組合字符串的指針遞增到最后一個斜杠以修剪路徑:
#define STRINGIFY(x) STRINGIFY_IMPL(x)
#define STRINGIFY_IMPL(x) #x
#define FILENAME __FILE__ ":" STRINGIFY(__LINE__)
constexpr const char* filename_without_path(const char* path) {
const char* result = path;
while(*path != '\0')
if(*path++ == '/') result = path;
return result;
}
// Usage:
constexpr const char* foo = filename_without_path(FILENAME);
std::cout << foo << std::endl;
您正在獲取臨時數組的地址。 實際上首先存儲數組,然后獲取地址。
constexpr auto p = // stores the array
formatFilename<str_size(file_name(__FILE__)), str_size(LINE_STRING)>(
file_name(__FILE__), LINE_STRING);
// than take the address
cout << p.data() << endl;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.