I am trying to build a simple c++ logger for learning purposes, but I seem to be stuck at the following issue. Let's say that I have a namespace that contains two functions as follows:
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);
}
}
and the main function is as follows:
int main(int argc, char** argv)
{
l::_p(__FILE__, __LINE__, 12, "%s", "Hello World!");
l::_p(__FILE__, __LINE__, "%s", "Hello World!");
return 0;
}
what I would like to have is a macro such that when the user types: l::p(12, "%s", "Hello World!");
it would be replaced by l::_p(__FILE__, __LINE__, 12, "%s", "Hello World!");
at compile time. Similarly when the user types l::p("%s", "Hello World!");
it would be replaced by l::_p(__FILE__, __LINE__, "%s", "Hello World!");
at compile time
what I would like to have is a macro such that when the user types:
l::p(12, "%s", "Hello World!");
it would be replaced byl::_p(__FILE__, __LINE__, 12, "%s", "Hello World!");
at compile time.
Sure, you can do:
#define p(...) _p(__FILE__, __LINE__, __VA_ARGS__)
Macros are processed at preprocessing stage at which point compiler is not aware about anything complicated like namespace. So such a macro can be confusing to unaware programmers that will later try to define a function named p
or call a function pointer named p
.
Preferably in C++ use stream-like interface with a macro instead like BOOST_LOG
does for example, (and since C++20 you could use source_location).