我正试图建立一个简单的c++日志器用于学习,但我似乎卡在了下面的问题上。假设我有一个命名空间,其中包含两个函数,如下所示。
namespace l {
void _p(const char* file, const int line, int vl, const char* fmt, ...) {
printf("%d:%s:%d: ", vl, file, line);
va_list __args;
va_start(__args, fmt);
vfprintf(stdout, fmt, __args);
printf("\n");
va_end(__args);
}
void _p(const char* file, const int line, const char* fmt, ...) {
printf("%s:%d: ", file, line);
va_list __args;
va_start(__args, fmt);
vfprintf(stdout, fmt, __args);
printf("\n");
va_end(__args);
}
}
而主函数如下:
int main(int argc, char** argv)
{
l::_p(__FILE__, __LINE__, 12, "%s", "Hello World!");
l::_p(__FILE__, __LINE__, "%s", "Hello World!");
return 0;
}
我希望有一个宏,当用户键入时, l::p(12, "%s", "Hello World!");
会被替换为 l::_p(__FILE__, __LINE__, 12, "%s", "Hello World!");
在编译时。同样,当用户输入 l::p("%s", "Hello World!");
取而代之的是 l::_p(__FILE__, __LINE__, "%s", "Hello World!");
在编译时
我希望有一个宏,当用户输入:
l::p(12, "%s", "Hello World!");
会被替换为l::_p(__FILE__, __LINE__, 12, "%s", "Hello World!");
在编译时。
当然,你可以这样做。
#define p(...) _p(__FILE__, __LINE__, __VA_ARGS__)
宏是在预处理阶段被处理的 这时编译器并不知道任何复杂的东西 比如命名空间。所以这样的宏可能会让不了解的程序员感到困惑,他们以后会尝试定义一个名为 p
或调用一个名为 p
.
在C++中,最好使用类似流的接口和一个宏来代替,如 BOOST_LOG
比如说,(从C++20开始,你可以用 来源地).
使用记录宏
#define LOG(...) l::_p(__FILE__, __LINE__, __VA_ARGS__)
void f(int i) {
LOG(12, "%d", i);
LOG("%d", i);
}