Search code examples
c++cvariadic-functionsvariadic-macros

C/C++ Variadic Macro Function Overloading


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


Solution

  • 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.

    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).