Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Recursive variadic macro

136 views
Skip to first unread message

pm

unread,
Oct 14, 2008, 3:04:55 AM10/14/08
to
Hi,
I want to create recursive variadic macro UNREFERENCED_PARAMETERS.
I want to use it this way:

int fn(int a, int b, int c)
{
UNREFERENCED_PARAMETERS(a,b,c);
return 0;
}

Is it possible to do in c++?
I thing that here is problem with expansion when just 1 parameter remain.
How to solve this problem?

here is my macro definition

#ifndef UNREFERENCED_PARAMETER
#define UNREFERENCED_PARAMETER(P) \
/*lint -save -e527 -e530 */ \
{ \
(P) = (P); \
} \
/*lint -restore */
#endif //UNREFERENCED_PARAMETER

#define UNREFERENCED_PARAMETERS(a1,...) UNREFERENCED_PARAMETER(a1);
UNREFERENCED_PARAMETERS(a1,__VA_ARGS__)


PM

Victor Bazarov

unread,
Oct 14, 2008, 9:37:45 AM10/14/08
to
pm wrote:
> Hi,
> I want to create recursive variadic macro UNREFERENCED_PARAMETERS.
> I want to use it this way:
>
> int fn(int a, int b, int c)
> {
> UNREFERENCED_PARAMETERS(a,b,c);
> return 0;
> }
>
> Is it possible to do in c++?
> I thing that here is problem with expansion when just 1 parameter remain.
> How to solve this problem?

Put them in another set of parentheses:

UNREFERENCED_PARAMETERS((a,b,c));

>
> here is my macro definition
>
> #ifndef UNREFERENCED_PARAMETER
> #define UNREFERENCED_PARAMETER(P) \
> /*lint -save -e527 -e530 */ \
> { \
> (P) = (P); \
> } \
> /*lint -restore */
> #endif //UNREFERENCED_PARAMETER
>
> #define UNREFERENCED_PARAMETERS(a1,...) UNREFERENCED_PARAMETER(a1);
> UNREFERENCED_PARAMETERS(a1,__VA_ARGS__)
>
>
> PM

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

pm

unread,
Oct 14, 2008, 10:12:23 AM10/14/08
to
Victor Bazarov wrote:
> Put them in another set of parentheses:
>
> UNREFERENCED_PARAMETERS((a,b,c));
>
It doesn't help.
There were one bug (parameter a1 cannot be used in last macro), but it
still doesn't work.

#define UNREFERENCED_PARAMETERS(a1,...) UNREFERENCED_PARAMETER(a1);
UNREFERENCED_PARAMETERS( __VA_ARGS__ )

After expansion I got this (result from preprocessed file):

int fn(int a, int b, int c)
{

(a); UNREFERENCED_PARAMETERS( b,c )
return 0;
}

PM

Victor Bazarov

unread,
Oct 14, 2008, 10:46:34 AM10/14/08
to

Perhaps you're overthinking it. Our "unused parameters" macro looks
very similar to

#define UNUSED_PARAMETER(a) (a)

And if you need a list, you just do

UNUSED_PARAMETER((a,b,c,d,e,f,g,h,i,j,k,l,m,n,o));

Eberhard Schefold

unread,
Oct 14, 2008, 12:06:01 PM10/14/08
to
pm wrote:

> I want to create recursive variadic macro UNREFERENCED_PARAMETERS.
> I want to use it this way:
>
> int fn(int a, int b, int c)
> {
> UNREFERENCED_PARAMETERS(a,b,c);
> return 0;
> }

Just to be sure (it's surprising how many programmers are not aware of
this): The most simple way for satisfying the compiler is to keep the
unreferenced parameter unnamed, as in

int fn( int, int, int /* c */ )
{
return 0;
}

This works also if the function had been declared

int fn(int a, int b, int c);

elsewhere.

Tim Roberts

unread,
Oct 15, 2008, 1:58:07 AM10/15/08
to
pm <pje...@gmail.com> wrote:

>Victor Bazarov wrote:
>> Put them in another set of parentheses:
>>
>> UNREFERENCED_PARAMETERS((a,b,c));
>>
>It doesn't help.

You didn't understand Victors suggestion. You are trying to generate code
like this:

(a);
(b);
(c);

However, that isn't necessary. The "comma" operator is a perfectly viable
operator in C. Thus, this works just as well to suppress the "unreferenced
parameter" warning:

(a,b,c);

So, you can just do this:

#define UNREFERENCED_PARAMETERS(a) (a)

int fn(int a, int b, int c)
{

UNREFERENCED_PARAMETERS((a,b,c));
return 0;
}
--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

pm

unread,
Oct 15, 2008, 3:26:07 AM10/15/08
to
Victor Bazarov wrote:
> Perhaps you're overthinking it. Our "unused parameters" macro looks
> very similar to
>
> #define UNUSED_PARAMETER(a) (a)
>
> And if you need a list, you just do
>
> UNUSED_PARAMETER((a,b,c,d,e,f,g,h,i,j,k,l,m,n,o));
>
> V

Hi!
It helps but there is one problem yet.

I used UNUSED_PARAMETER macro inside IMPLEMENT_SIMPLE_FN(see bellow).
IMPLEMENT_SIMPLE_FN is used in another macros!!!

#define IMPLEMENT_SIMPLE_FN(_tret, _name, _params_declaration, _params,
_failret) \
extern "C" _tret _name##_params_declaration \
{ \
UNUSED_PARAMETER(##_params##); \
return _failret; \
}


Usage of IMPLEMENT_SIMPLE_FN:
IMPLEMENT_SIMPLE_FN(int, dummyFn, (int a, int b, int c), (a,b,c), -1)

This generates this function:
extern "C" int dummyFn(int a, int b, int c)
{
((a,b,c));
return -1;
}

In my case problem occurs when I have function without parameters:
IMPLEMENT_SIMPLE_FN(int, noParametersFn, (), (), -1)
This generates:
extern "C" int noParametersFn()
{ (());
return -1;
}


Problem is: (());
Have you any idea how to solve this without changing IMPLEMENT_SIMPLE_FN
parameters?

I cannot use Eberhard’s idea (I know about it) because I’m using
IMPLEMENT_SIMPLE_FN this way too:

int emulate_dummyFn(int a, int b, int c)
{
return a+b+c;
}

IMPLEMENT_SIMPLE_FN(int, dummyFn, (int a, int b, int c), (a,b,c),
emulate_dummyFn(a,b,c));

Thanks

PM

Victor Bazarov

unread,
Oct 15, 2008, 9:18:09 AM10/15/08
to
pm wrote:
> Victor Bazarov wrote:
>> Perhaps you're overthinking it. Our "unused parameters" macro looks
>> very similar to
>>
>> #define UNUSED_PARAMETER(a) (a)
>>
>> And if you need a list, you just do
>>
>> UNUSED_PARAMETER((a,b,c,d,e,f,g,h,i,j,k,l,m,n,o));
>>
>> V
>
> Hi!
> It helps but there is one problem yet.
>
> I used UNUSED_PARAMETER macro inside IMPLEMENT_SIMPLE_FN(see bellow).
> IMPLEMENT_SIMPLE_FN is used in another macros!!!
>
> #define IMPLEMENT_SIMPLE_FN(_tret, _name, _params_declaration, _params,
> _failret) \
> extern "C" _tret _name##_params_declaration \
> { \
> UNUSED_PARAMETER(##_params##); \
> return _failret; \
> }
>
>
> Usage of IMPLEMENT_SIMPLE_FN:
> IMPLEMENT_SIMPLE_FN(int, dummyFn, (int a, int b, int c), (a,b,c), -1)
>
> This generates this function:
> extern "C" int dummyFn(int a, int b, int c)
> {
> ((a,b,c));
> return -1;
> }

OK, hold on. Why in the world do you *need* the named arguments in such
a simple function? Why can't you simply require the list of argument
types instead of named arguments? IOW:

#define IMPLEMENT_SIMPLE_FN(_tret, _name, \
_param_types, _failret) \
extern "C" _tret _name##_param_types \
{ \
return _failret; \
}

...

IMPLEMENT_SIMPLE_FN(int, dummyFn, (int,double,char*), -1)

And if somebody supplies names for those arguments, it's their own
fault. <weakg>

pm

unread,
Oct 16, 2008, 11:43:13 AM10/16/08
to

Because we have a lot of code where is used this way

IMPLEMENT_SIMPLE_FN(int, dummyFn, (int a, int b, int c), (a,b,c),

emulate_dummyFn(a,b,c));

or (parameter order is changed)

IMPLEMENT_SIMPLE_FN(int, dummyFn, (int a, int b, int c), (a,b,c),

emulate_dummyFn(c,b,a));

or (some parameters are replaced by constant)

IMPLEMENT_SIMPLE_FN(int, dummyFn, (int a, int b, int c), (a,b,c),

emulate_dummyFn(0,b,a));

unfortunately this is quite often in our code which is in a lot of files.

PM

Victor Bazarov

unread,
Oct 16, 2008, 12:08:54 PM10/16/08
to


Try

void PARAM_EATER(...) {}


#define IMPLEMENT_SIMPLE_FN(_tret, _name, \
_params_declaration, _params, _failret) \
extern "C" _tret _name##_params_declaration \
{ \

PARAM_EATER _params; \
return _failret; \
}

IMPLEMENT_SIMPLE_FN(int, foo, (void *a, char b), (a,b), 0);
IMPLEMENT_SIMPLE_FN(int, bar, (), (), 0);

int main()
{
foo(0, 'a');
return bar();

0 new messages