greywolf82
greywolf82

Reputation: 22173

Macro variadic argument

I have this code:

std::string format(const char *fmt, ...);

#define DEBUG(HANDLER, LEVEL, ...) LOG##LEVEL(HANDLER, format(__VA_ARGS__))

It works when I use:

DEBUG(handler, DEBUG, "var is %d\n", 15);

but it doesn't work when I use:

DEBUG(handler, DEBUG, "test");

How can I check if there's only one argument or more than one?
I need to use C++98 solution only.

Upvotes: 2

Views: 93

Answers (2)

Duck Dodgers
Duck Dodgers

Reputation: 3461

So, I looked at your question and I looked at your code and I realized that this is probably a case of the infamous XY Problem.

Although you say, you want to count the number of arguments being passed to the macro, what you want to do is write debug messages which do not have any other parameters except a literal string which states a debug message as you show in the example.

DEBUG(handler, DEBUG, "test");

But that is of course possible. And to test it, I wrote the following bit of code.

std::string format(const char* fmt, ...) {
    char buffer[256];
    std::cout << __FUNCTION__ << std::endl;
    va_list argList;
    va_start(argList, fmt);
    vsprintf(buffer, fmt, argList);
    va_end(argList);
    return std::string(buffer);
}

#define TRC(...) {\
    std::cout << "MACRO!" << std::endl; \
    std::cout << format(__VA_ARGS__);\
}

int main()
{
    std::cout << "Hello World!" << std::endl;
    const char *t = "b";
    TRC("[%s] bla bla [%d]\n", t, 9);
    TRC("test");
    return 0;
}

which produces the output,

Hello World!
MACRO!
format
[b] bla bla [9]
MACRO!
format
test

Like I mentioned in the comments to your question earlier, I have C++03 compiler but this should work for C++98 also, I guess.

Question:

"How can I check if there's only one argument or more than one?"

The variadic macro itself has no problem whether you have one argument or more.

But if you really really still want to count the number of arguments passed in, I don't know of anyway in C++03 or earlier to do that.

Upvotes: 1

Michael Veksler
Michael Veksler

Reputation: 8475

Since __VA__ARGS__ is available on your otherwise C++98 compiler (despite being a C++11 feature), there is a chance it also has __VA_OPT__ as an extension:

You should use __VA_OPT__(something) (which is a C++20 feature) to make the comma appear only if there is at least one argument:

#define DEBUG(HANDLER, LEVEL, ...) LOG##LEVEL(HANDLER __VA_OPT__( format(__VA_ARGS__)))

or something similar that works for your case.

Upvotes: 1

Related Questions