how to generate this code?

R

Roberto Gori

Hi all,

i'm looking for a way, a tool or a macro like this:

USEFULMACRO(foo, bar, type1 arg1, type2 arg2, ..., typeN argN)

to generate the following code:

void foo(type1 arg1, type2 arg2, ..., typeN argN)
{
bar(arg1, arg2, ..., argN);
}

N is variable.
The function "foo" invokes "bar" with the same arguments list.
All the C++ types are admitted (function pointers included).

Some idea?
 
V

Victor Bazarov

Roberto said:
i'm looking for a way, a tool or a macro like this:

USEFULMACRO(foo, bar, type1 arg1, type2 arg2, ..., typeN argN)

to generate the following code:

void foo(type1 arg1, type2 arg2, ..., typeN argN)
{
bar(arg1, arg2, ..., argN);
}

N is variable.
The function "foo" invokes "bar" with the same arguments list.
All the C++ types are admitted (function pointers included).

Some idea?

Since you have to separate names of arguments from their types in the
macro when it's generated, you need to separate them in the macro arg
list:

USEFULMACRO(foo, bar, type1, arg1, ...

Otherwise "type1 arg1" is a single preprocessing token, and there are no
means to "split" it into two using any preprocessor mechanisms.

Since you want a variable number of arguments, you need a compiler
capable of macros with variable number of arguments, otherwise you have
to generate all macros up to maximum number of args your system is going
to handle. See "variadic macro" in the archives. Some compilers can do
that. It's not a standard construct yet, though.

V
 
R

Ron Natalie

Roberto said:
Hi all,

i'm looking for a way, a tool or a macro like this:

USEFULMACRO(foo, bar, type1 arg1, type2 arg2, ..., typeN argN)

to generate the following code:

void foo(type1 arg1, type2 arg2, ..., typeN argN)
{
bar(arg1, arg2, ..., argN);
}

N is variable.
The function "foo" invokes "bar" with the same arguments list.
All the C++ types are admitted (function pointers included).

Some idea?
Can't be done. First, there is no such concept as
variable arguments in the middle of the arg list. They
must be at the end. Second, the only thing you can
do with variable args is extract them with the cstdarg
macros. You can't pass them en masse to another ...
expecting function.
 
V

Victor Bazarov

Ron said:
Can't be done. First, there is no such concept as
variable arguments in the middle of the arg list. They
must be at the end. Second, the only thing you can
do with variable args is extract them with the cstdarg
macros. You can't pass them en masse to another ...
expecting function.

I don't think the variable arguments in the middle is what OP wants. I
also don't think that passing them en masse is the goal. Let's say we
only have three (or four, depending on how you count) things there:

USEFULMACRO(foo, bar, type arg)

What would be its definition so it is possible to generate this code:

void foo(type arg) {
bar(arg);
}

?

Methinks the problem is trying to extract the second word (token) "arg"
from the third macro argument.

V
 
P

Phlip

Roberto said:
i'm looking for a way, a tool or a macro like this:

USEFULMACRO(foo, bar, type1 arg1, type2 arg2, ..., typeN argN)

Long argument lists are a "design smell". That means they are an indicator
that other parts of your design could be better.

Why aren't all those arguments elements of a collection, such as an
std::map<>? Or even data stored in a class?
 
R

Roberto Gori

Victor Bazarov said:
Since you have to separate names of arguments from their types in the
macro when it's generated, you need to separate them in the macro arg
list:

USEFULMACRO(foo, bar, type1, arg1, ...

Otherwise "type1 arg1" is a single preprocessing token, and there are no
means to "split" it into two using any preprocessor mechanisms.

I think that when the argument is a function pointer (something like float
(*pt2Func)(float, float) ) it's not possible to separate the tokens with
commas.
 
J

Jakob Bieling

Roberto Gori said:
I think that when the argument is a function pointer (something like
float (*pt2Func)(float, float) ) it's not possible to separate the
tokens with commas.

Use a typedef, then it works.

regards
 
V

Victor Bazarov

Roberto said:
Roberto said:
i'm looking for a way, a tool or a macro like this:

USEFULMACRO(foo, bar, type1 arg1, type2 arg2, ..., typeN argN)

to generate the following code:

void foo(type1 arg1, type2 arg2, ..., typeN argN)
{
bar(arg1, arg2, ..., argN);
}

N is variable.
The function "foo" invokes "bar" with the same arguments list.
All the C++ types are admitted (function pointers included).

Some idea?
[..]

I think that when the argument is a function pointer (something like
float (*pt2Func)(float, float) ) it's not possible to separate the
tokens with commas.

Right. That's why using macro is not a good idea. Perhaps you could use
some custom pre-processor. Something like TrollTech's "moc"...

V
 
R

Roberto Gori

Victor Bazarov said:
Roberto said:
Roberto Gori wrote:
i'm looking for a way, a tool or a macro like this:

USEFULMACRO(foo, bar, type1 arg1, type2 arg2, ..., typeN argN)

to generate the following code:

void foo(type1 arg1, type2 arg2, ..., typeN argN)
{
bar(arg1, arg2, ..., argN);
}

N is variable.
The function "foo" invokes "bar" with the same arguments list.
All the C++ types are admitted (function pointers included).

Some idea?
[..]

I think that when the argument is a function pointer (something like
float (*pt2Func)(float, float) ) it's not possible to separate the
tokens with commas.

Right. That's why using macro is not a good idea. Perhaps you could use
some custom pre-processor. Something like TrollTech's "moc"...

I suspect you are right and moc it's not free. :(
 
V

Victor Bazarov

Roberto said:
Victor Bazarov said:
[..] Perhaps you
could use some custom pre-processor. Something like TrollTech's
"moc"...

I suspect you are right and moc it's not free. :(

I wasn't suggesting that you acquired (licensed) 'moc' from TrollTech.
But you can probably write your own, the tools to parse C++ source code
are all there, and there's probably plenty of free ones on the Web.

V
 
R

Roberto Gori

Victor Bazarov said:
Roberto said:
Victor Bazarov said:
[..] Perhaps you
could use some custom pre-processor. Something like TrollTech's
"moc"...

I suspect you are right and moc it's not free. :(

I wasn't suggesting that you acquired (licensed) 'moc' from TrollTech.
But you can probably write your own, the tools to parse C++ source code
are all there, and there's probably plenty of free ones on the Web.

Many thanks Victor.

i'm searching in the Web.
 
P

Phlip

Roberto said:
Victor Bazarov wrote:

Many thanks Victor.

A> I thought Trolltech's Moc system, itself, was Free as in Beer, and
that only the high-end Qt was payware. I could be wrong, but...

B> Adding keywords to your language (that's what Moc does) is not
a healthy way to add variable arguments to your macro.

You could do this:

MACRO(target, (arg1, arg2, arg3, argN))

Then only one macro parameter can represent all the variable arguments, with
their ().

Next, you could answer my question about what problem you are trying to
solve. There could be a cleaner way to do it that doesn't need a macro.

(BTW: Add keywords to the language just so we can abuse a macro? There just
aren't words..!)
 
R

Roberto Gori

Phlip said:
A> I thought Trolltech's Moc system, itself, was Free as in Beer, and
that only the high-end Qt was payware. I could be wrong, but...

B> Adding keywords to your language (that's what Moc does) is not
a healthy way to add variable arguments to your macro.

I agree with you but ...
You could do this:

MACRO(target, (arg1, arg2, arg3, argN))

Then only one macro parameter can represent all the variable arguments,
with their ().

.... this macro is able to generate (with all types and names):

foo(arg1, arg2, arg3, argN)

but not:

bar(name_of_arg1, name_of_arg2, name_of_arg3, name_of_argN);
Next, you could answer my question about what problem you are trying to
solve. There could be a cleaner way to do it that doesn't need a macro.

the problem is to generate a code like this:

void foo(int a, char b, void (*f)(int), double g[], float c=5)
{
bar(a, b, f, g, c);
}

starting from some function name (foo) and some arguments list (int a, char
b, void (*f)(int), double g[], float c=5)

Maybe your question is: why foo must invoke bar in this way, with the same
parameters?
Bacause i want to generate a class (the owner of foo) that support a typed
callback (bar).
 
P

Phlip

Roberto said:
the problem is to generate a code like this:

What is the _outer_ problem? You envision a solution. What is the problem
that solution might solve?
Maybe your question is: why foo must invoke bar in this way, with the same
parameters?
Bacause i want to generate a class (the owner of foo) that support a
typed callback (bar).

Please provide some pseudo-code showing this rig in use, with its callers.
 
H

Howard

Maybe your question is: why foo must invoke bar in this way, with the same
parameters?
Bacause i want to generate a class (the owner of foo) that support a
typed callback (bar).

Then perhaps what you want is some kind of dispatch mechanism?

For example, we have some software which has a single global callback
function, which receives a pointer to an instance of the class in question.
This calback simply calls a "dispatcher" member function of the class using
that instance pointer, so that we can manipulate the specific instance as
needed.

We also pass a pointer to a structure containing information about what we
want the object to actually do. It contains an integer (enum) code that
tells us what we want to do, followed by the data we want to work on. We
use a short array of float values, but you could use a string, or a vector
of floats, or a vector of "generic" objects (I think Boost has some kind of
generic object holder).

The dispatcher uses a switch statement to call a sepcific function, passing
it the parameters from our array which are appropriate for the function
being performed.

Just a thought...

-Howard
 
R

Roberto Gori

Phlip said:
What is the _outer_ problem? You envision a solution. What is the problem
that solution might solve?


Please provide some pseudo-code showing this rig in use, with its callers.

class Observer
{
virtual void OnEvent(arglist)
{
//do something
}
}

class Event
{
Observer *obs;
void Notify(arglist) {
obs->OnEvent(arglist)
}
}

void main ()
{
Event e;
Observer o;

e.obs = &o;

//in some case someone calls
e.Notify(arglist);
}

to give this example i simplified all the object interfaces but my aim is to
have multiple events with different arglists.
 
R

Roberto Gori

Howard said:
Then perhaps what you want is some kind of dispatch mechanism?

Exactly Howard!
For example, we have some software which has a single global callback
function, which receives a pointer to an instance of the class in
question. This calback simply calls a "dispatcher" member function of the
class using that instance pointer, so that we can manipulate the specific
instance as needed.

We also pass a pointer to a structure containing information about what we
want the object to actually do. It contains an integer (enum) code that
tells us what we want to do, followed by the data we want to work on. We
use a short array of float values, but you could use a string, or a vector
of floats, or a vector of "generic" objects (I think Boost has some kind
of generic object holder).

The dispatcher uses a switch statement to call a sepcific function,
passing it the parameters from our array which are appropriate for the
function being performed.

I understand this method but i would like to avoid the packing/unpacking of
parameters because this could be unefficient and error prone.
Moreover i would like to preserve legacy code by inserting only the call to
the notification routine.

for example:

if i have a Foo class i would like to extend them in this way

class NewFoo: public EventNotifier
{
void SomeMethod( ...)
{
.....
NotifyEvent(val1, val2, ....);
.....
}
}
 
P

Phlip

Roberto said:
e.Notify(arglist);
}

to give this example i simplified all the object interfaces but my aim is
to have multiple events with different arglists.

So arglist is an object with a list of arguments inside it.

All GUIs use this pattern for their event queues. The raw event has a short
list of parameters, and custom events for advanced inputs, such as a list
box selection, have longer lists, such as the index of the selected item.
 
R

Roberto Gori

Phlip said:
So arglist is an object with a list of arguments inside it.

i would prefer arglist as a list of arguments and not an object because i
would like to reuse directly callbacks of a legacy code (like OnEvent(int x,
int y)) without packing/unpacking the parameters in some object/structure.
 
P

Phlip

Roberto said:
i would prefer arglist as a list of arguments and not an object because i
would like to reuse directly callbacks of a legacy code (like OnEvent(int
x, int y)) without packing/unpacking the parameters in some
object/structure.

If a legacy code had a poor design, I would work harder to fix that than to
adapt to it.

However, you can easily get your technique here:

http://www.codeproject.com/macro/metamacros.asp
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top