views:

50

answers:

3

Hi,

I want to create macros that will insert a parameter into a function call. For example, I have function Action() declared below. Action takes as it's inputs an enum for the state number and a formatted string with optional args for the string.

I want to define macros so that instead of calling Action( ActionState1, "someText %d", &arg) with ActionState1 for the state parameter, I can just call State1("someText %d", &arg) instead. That way the macro would stick in the ActionState1 for the state param for me. I'm thinking of something like the following:

#define State1(formatedString, ...) Action(ActionState1, formatedString, ...)
#define State2(formatedString, ...) Action(ActionState2, formatedString, ...)
#define State3(formatedString, ...) Action(ActionState3, formatedString, ...)

enum {
  ActionState1,
  ActionState2,
  ActionState3
}

static void Action( State state, String formatedString, ...);

Does anyone know what the proper format for this would be?

Thanks

+2  A: 

No this cannot be done using the preprocessor. The preprocessor allows you to string up entities but not go the reverse way. For what you want, you will need to break up State1 to two components State and 1 (the latter being more important) and proceed with the call.

However, the more important question is why would you want to do this? You hardly save any typing by such a transformation or gain readability.

You could get something nearby using templates though:

template <size_t N> 
T State(string fmt, ...) { return Action(N, fmt, ...); } // assume T Action(size_t, ...);

and use the above as:

State<1>(fmtStr, ...);
State<2>(fmtStr2, ...);

But again, there's hardly any syntactic gain here IMO.

dirkgently
What I left out in my example is that the 1, 2, 3 are represented by enum variables that become extremely long, kinda like ClassA::EnumA::State1, in which case using something like State<ClassA::EnumA::State1>(string fmt, ...) would be a bit of a hassle to type versus State1(string fmt, ...), but if you have a better suggestion I'm all ears :) Thanks for the input
Zain
+2  A: 

I believe that __VA_ARGS__ is what you're looking for:

#define State1(formattedString, ...) Action(1, (formattedString), __VA_ARGS__)
 .
 .
 .

This is a C99 feature, and Wikipedia claims that they are not part of any official C++ standard (I note this because you use the C++ tag), but a fairly popular extension. There is some good discussion over at this question.

Jack Kelly
The OP wanted: _the macro would stick in the state = 1 bit for me_. I don't see how `__VA_ARGS__` may help. IMHO, the ellipses are not to be taken to represent a variadic function `Action`. But I may be wrong.
dirkgently
Thanks, this is exactly what I wanted
Zain
I think `Action` needs to be variadic because the OP's question has a format string in the example.
Jack Kelly
It's probably worth noting that this is a C99 feature.
Mark B
Yes, it probably is. Thanks.
Jack Kelly
A: 

Why do you want to create such a thing? In C++ Prefer to use streaming operators or similar over using varargs as it gains type safety among other things.

I don't believe there's any way to do what you want in C++ preprocessor macros. If you had a va_list version of Action, you might be able to get away with something like the following, but I seem to recall that the parameter before the ... must be POD - unfortunately a quick search can't confirm or deny that.

#include <cstdarg>
inline void State1(String formatedString, ...)
{
    va_list args;
    va_start(args, formatedString);
    Action(1, formatedString, args);
    va_end(args);
}
Mark B
I've got the va_list stuff inside Action. I just needed to pass it the state parameter as well. Do you know a better way to accomplish this without defining a new function for every instance of State? I'm doing it this way because I have 7 different states
Zain