[英]How to get filename from __FILE__ and concat with __LINE__ at compile time
I'm trying to concat filename and line without path at compile time.我试图在编译时连接文件名和没有路径的行。 Like
/tmp/main.cpp20
-> main.cpp:20
像
/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;
}
But it seems not work and return a compilation error但它似乎不起作用并返回编译错误
main.cpp: In function 'int main()': main.cpp:46:46: error: call to non-'constexpr' function 'std::array<_Tp, _Nm>::value_type& std::array<_Tp, _Nm>::operator[](std::array<_Tp, _Nm>::size_type) [with _Tp = char;
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;
long unsigned int _Nm = 12; std::array<_Tp, _Nm>::reference = char&;
std::array<_Tp, _Nm>::reference = char&; std::array<_Tp, _Nm>::value_type = char;
std::array<_Tp, _Nm>::value_type = char; std::array<_Tp, _Nm>::size_type = long unsigned int]'
std::array<_Tp, _Nm>::size_type = long unsigned int]'
Is there any way to do it at compile time?有没有办法在编译时做到这一点?
For your specific case (getting the filename without path and the line number) there are a few easier approaches that you might want to use:对于您的特定情况(获取没有路径和行号的文件名),您可能想要使用一些更简单的方法:
__FILE_NAME__
instead of __FILE__
__FILE_NAME__
代替__FILE__
Both gcc and clang support the __FILE_NAME__
macro, that just resolves to the filename instead of the full file path. gcc 和 clang 都支持
__FILE_NAME__
宏,它只是解析为文件名而不是完整的文件路径。
Utilizing those you can write it as a single macro:利用那些你可以把它写成一个宏:
#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 unfortunately doesn't offer the __FILE_NAME__
macro, but you could utilize the /FC
compiler switch to specify if you want the full path for __FILE__
or just the filename.不幸的是,msvc 不提供
__FILE_NAME__
宏,但您可以使用/FC
编译器开关来指定您是否需要__FILE__
的完整路径或只是文件名。
-- --
Adjacent character sequences are automatically combined by the compiler - eg "a" "b" "c"
would be combined into "abc"
.相邻的字符序列由编译器自动组合- 例如
"a" "b" "c"
将组合成"abc"
。
You can use this to let the compiler do the concatenation for you.您可以使用它让编译器为您进行连接。
After that we can just increment the pointer to that combined string past the last slash to trim off the path:之后,我们可以将指向该组合字符串的指针递增到最后一个斜杠以修剪路径:
#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;
You are taking an address of a temporary array.您正在获取临时数组的地址。 Actually first store the array, then take the address.
实际上首先存储数组,然后获取地址。
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.