Macro Expansion

R

Ryan

Below I have a series of defined macros. When ISVALID_TEST is called the compiler is complaining the macro doesn't have enough actual parameters. This means NOINPUT isn't expanding. The definition of ISVALID_TEST uses the UnitTest++ framework. This isn't an issue but unless you have it it won't compile. It is shown here to explain the macro signature.

How can I get NOINPUT to take the place of Kpos, Kvel and Kacc in the macrocall instead of all being stuffed into Kpos?

Ryan


#define P99_PROTECT(...) __VA_ARGS__

#define NOINPUT P99PROTECT(false, false, false)

#define ISVALID_TEST(TestName, Kpos, Kvel, Kacc) \
TEST(TestName) \
{ \
point = std::make_shared<KinematicState>(); \
if (Kpos) point->set(position); \
}

//This line complains the macro doesn't have enough actual parameters
ISVALID_TEST(NoInput, NOINPUT);

//Works fine.
ISVALID_TEST(NoInput2, false, false, false);
 
A

Alf P. Steinbach

Below I have a series of defined macros. When ISVALID_TEST is called
the compiler is complaining the macro doesn't have enough actual
parameters. This means NOINPUT isn't expanding. The definition of
ISVALID_TEST uses the UnitTest++ framework. This isn't an issue but
unless you have it it won't compile. It is shown here to explain the
macro signature.

How can I get NOINPUT to take the place of Kpos, Kvel and Kacc in the
macro call instead of all being stuffed into Kpos?


#define P99_PROTECT(...) __VA_ARGS__

#define NOINPUT P99PROTECT(false, false, false)

#define ISVALID_TEST(TestName, Kpos, Kvel, Kacc) \
TEST(TestName) \
{ \
point = std::make_shared<KinematicState>(); \
if (Kpos) point->set(position); \
}

//This line complains the macro doesn't have enough actual parameters
ISVALID_TEST(NoInput, NOINPUT);

//Works fine.
ISVALID_TEST(NoInput2, false, false, false);


First, thanks for the (implicit) link to the P99 library, I didn't know
about it!

Now, macro stuff is a black art. Different compilers do things
differently. The holy Standard is at best a rough guide here.

So, instead of somehow managing to get your macro expanded up front,
which I don't know if is possible (and I suspect it isn't possible),
consider an alternative, just applying general good practice:


{code]
#include <iostream>
using namespace std;

#define P99_PROTECT(...) __VA_ARGS__
#define TEST( name ) void name()

#define KPOS( p, v, a ) p
#define KVEL( p, v, a ) v
#define KACC( p, v, a ) a

#define NOINPUT P99_PROTECT( (false, false, false) )

#define ISVALID_TEST(TestName, KParams ) \
TEST(TestName) \
{ \
cout \
<< KPOS KParams \
<< ", " << KVEL KParams \
<< ", " << KACC KParams \
<< endl; \
}

// This line no longer complains about not enough actual parameters
ISVALID_TEST( NoInput1, NOINPUT )

// Also works fine.
ISVALID_TEST(NoInput2, (1, 2, 3) )

auto main() -> int
{
NoInput1();
NoInput2();
}
[/code]


Cheers & hth.,

- Alf

PS: You can find a lot of advanced macro stuff in Boost, in particular
in the Boost Preprocessor and Boost Parameters sub-libraries.
 
R

Ryan

#define NOINPUT P99_PROTECT( (false, false, false) )

Took a couple of minutes to catch the extra parenthesis here. :)

<< KPOS KParams \

I get that KPOS KParams is really KPOS (false, false, false) because of the extra parenthesis defined above. I Really like the look though of passing KParams to KPOS like this.

KPOS (KParams)

I believe though this just moves the problem I had with ISVALID_TEST to KPOS. So there is no way to accomplish this the other way?

PS: You can find a lot of advanced macro stuff in Boost, in particular
in the Boost Preprocessor and Boost Parameters sub-libraries.

I have seen there macro stuff. It's pretty crazy.

Thanks for the help.

Ryan
 
A

Alf P. Steinbach

Took a couple of minutes to catch the extra parenthesis here. :)



I get that KPOS KParams is really KPOS (false, false, false) because of the
extra parenthesis defined above.
Yes.


I Really like the look though of passing
KParams to KPOS like this.

KPOS (KParams)

I believe though this just moves the problem I had with ISVALID_TEST to KPOS.

Yes, arguments are passed literally as they are (and only expanded on
the receiving end), and here KParams is an argument.

But now that the problem is in a macro that you control the definition
of, you can handle it one level down:

#define KPOS_( p, v, a ) p
#define KPOS( args ) KPOS_ args

Disclaimer: untouched by compiler's hands.

So there is no way to accomplish this the other way?

Sorry no, I have no further ideas, other than the obvious (?) ones of
using some less macro-oriented test framework and/or generating C++ code
from a script language such as Python?

Or, come to think of it, I don't understand the /purpose/ of
P99_PROTECT, so if you don't like the above maybe you can just ditch the
P99_PROTECT wrapping?


Cheers & hth.,

- Alf
 
R

Ryan

#define KPOS_( p, v, a ) p
#define KPOS( args ) KPOS_ args

Yeah, I don't think I'll add an extra indirection to the macros just to get the look I want. When someone come behind me to maintain it I don't want it to be that bad.

Sorry no, I have no further ideas, other than the obvious (?) ones of
using some less macro-oriented test framework and/or generating C++ code
from a script language such as Python?

That's okay. I appreciate the help. Thank you.

Ryan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top