Discussion:
Are For loops macros possible?
(too old to reply)
Nobody
2010-02-28 18:00:59 UTC
Permalink
I am implementing a callback function for multiple callbacks, but the
callback function does not have a parameter such as a handle or number to
tell which callback the call is for. I have no control over it, so I can't
add my own parameters, so I have to provide different entry points that
calls a centralized routine with a sequence number. So I have functions like
this:

int func0(int para1,int para2) { return func(0,para1,para2);};
int func1(int para1,int para2) { return func(1,para1,para2);};
int func2(int para1,int para2) { return func(2,para1,para2);};
int func3(int para1,int para2) { return func(3,para1,para2);};
...

I plan to use a macro like this to generate the above using the
Token-Pasting Operator (##):

#define paster( n ) int func##n(int para1,int para2) { return
func(##n,para1,para2);}

So, to generate the above, I would use:

paster(0);
paster(1);
paster(2);
paster(3);
...

Is there a way to repeatedly call the macro a fixed number of times?
Something like #while or #for loop? Currently, I am using an Excel sheet to
generate the code. Example:

= "paster(" & A1 & ");"

Cells A1 to Ann contain sequence numbers filled by Edit-->Fill-->Series, so
I only have to do one copy and paste.

I am using VC6 and 2003.

Thank you
Igor Tandetnik
2010-02-28 18:23:31 UTC
Permalink
Post by Nobody
I am implementing a callback function for multiple callbacks, but the
callback function does not have a parameter such as a handle or number to
tell which callback the call is for. I have no control over it, so I can't
add my own parameters, so I have to provide different entry points that
calls a centralized routine with a sequence number. So I have functions like
int func0(int para1,int para2) { return func(0,para1,para2);};
int func1(int para1,int para2) { return func(1,para1,para2);};
int func2(int para1,int para2) { return func(2,para1,para2);};
int func3(int para1,int para2) { return func(3,para1,para2);};
I plan to use a macro like this to generate the above using the
Consider a template instead:

template <int seq>
int func(int para1, int para2) { return func(seq, para1, para2); }

func<2>(42, 84);
Post by Nobody
#define paster( n ) int func##n(int para1,int para2) { return
func(##n,para1,para2);}
You don't need second ##. Drop it.
Post by Nobody
Is there a way to repeatedly call the macro a fixed number of times?
Use the template, and you wouldn't need to. If for some strange reason you insist on using macros, there might be something like this in Boost Preprocessor library:

http://www.boost.org/doc/libs/1_42_0/libs/preprocessor/doc/index.html
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Nobody
2010-03-01 01:21:53 UTC
Permalink
I don't think template functions work in this case, but I see that the Boost
library has constructs that allow looping.

Thank you
Post by Nobody
I am implementing a callback function for multiple callbacks, but the
callback function does not have a parameter such as a handle or number to
tell which callback the call is for. I have no control over it, so I can't
add my own parameters, so I have to provide different entry points that
calls a centralized routine with a sequence number. So I have functions like
int func0(int para1,int para2) { return func(0,para1,para2);};
int func1(int para1,int para2) { return func(1,para1,para2);};
int func2(int para1,int para2) { return func(2,para1,para2);};
int func3(int para1,int para2) { return func(3,para1,para2);};
I plan to use a macro like this to generate the above using the
Consider a template instead:

template <int seq>
int func(int para1, int para2) { return func(seq, para1, para2); }

func<2>(42, 84);
Post by Nobody
#define paster( n ) int func##n(int para1,int para2) { return
func(##n,para1,para2);}
You don't need second ##. Drop it.
Post by Nobody
Is there a way to repeatedly call the macro a fixed number of times?
Use the template, and you wouldn't need to. If for some strange reason you
insist on using macros, there might be something like this in Boost
Preprocessor library:

http://www.boost.org/doc/libs/1_42_0/libs/preprocessor/doc/index.html
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily
a good idea. It is hard to be sure where they are going to land, and it
could be dangerous sitting under them as they fly overhead. -- RFC 1925
Igor Tandetnik
2010-03-01 03:19:36 UTC
Permalink
Post by Nobody
I don't think template functions work in this case
Why not, pray tell? Have you tried it?
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Nobody
2010-03-01 04:36:20 UTC
Permalink
I haven't used templates much, but the solution that you suggested is a
substitute for the macro, which is fine, but I think I still have to list
the line multiple times, which is what I am trying to avoid. Example:

func<0>(42, 84);
func<1>(42, 84);
func<2>(42, 84);

I can't use something like a loop construct, except by using Boost library,
or similar.
Post by Nobody
I don't think template functions work in this case
Why not, pray tell? Have you tried it?
Igor Tandetnik
2010-03-01 05:07:32 UTC
Permalink
Post by Nobody
I haven't used templates much, but the solution that you suggested is a
substitute for the macro, which is fine, but I think I still have to list
func<0>(42, 84);
func<1>(42, 84);
func<2>(42, 84);
Only if you want to actually make three calls in a row. You certainly don't have to declare each template instantiation separately.
Post by Nobody
I can't use something like a loop construct, except by using Boost library,
or similar.
Well, the code above could be written as

for (int i = 0; i < 3; ++i) {
func(i, 42, 84);
}


What are you really trying to achieve? Show a sample of your current code, with macros, and I'll show you how to do it with templates.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Nobody
2010-03-01 09:10:39 UTC
Permalink
Here is a sample without Macros:

// Central function: Has 3 parameters, the first is sequence number
// This function does the real work.
int func(int seq, int para1,int para2)
{
// Some code
};

// "n" functions: Have 2 parameters. They call the central function.
int func0(int para1,int para2) { return func(0,para1,para2);};
int func1(int para1,int para2) { return func(1,para1,para2);};
int func2(int para1,int para2) { return func(2,para1,para2);};
int func3(int para1,int para2) { return func(3,para1,para2);};


With Macros(func stays the same as above), no Boost library use:

#define paster(n) int func##n(int para1,int para2) {return
func(n,para1,para2);}

paster(0);
paster(1);
paster(2);
paster(3);

Note how paster macro is used outside any function since it basically
expands to an entire function. There is no advantage for this macro except
it makes it easy to read, and I only need to change one line if I change
function names or data type.

When setting up the call back, I use another macro to fill an array with
function pointers. Example:

MYPROC ProcArray[APPMAX] = {0};

#define PasteProcArray(n) ProcArray[n] = (MYPROC) func##n; i++

void InitProcArray(void)
{
int i=0;

PasteInitProcArray(0);
PasteInitProcArray(1);
PasteInitProcArray(2);
PasteInitProcArray(3);

if (i!=APPMAX) {
// Part of the array was not defined
MessageBox(NULL,_T("Size error in InitProcArray."), NULL, MB_OK);
}
}

And the callback code:

int i, id;

for (i=0;i<APPMAX;i++) {
id = GetNextID()
SetCallBack(id, ProcArray[i]);
// id is not given to the callback, so different function
// pointers are required in this case.
}
Post by Nobody
I haven't used templates much, but the solution that you suggested is a
substitute for the macro, which is fine, but I think I still have to list
func<0>(42, 84);
func<1>(42, 84);
func<2>(42, 84);
Only if you want to actually make three calls in a row. You certainly don't
have to declare each template instantiation separately.
Post by Nobody
I can't use something like a loop construct, except by using Boost library,
or similar.
Well, the code above could be written as

for (int i = 0; i < 3; ++i) {
func(i, 42, 84);
}


What are you really trying to achieve? Show a sample of your current code,
with macros, and I'll show you how to do it with templates.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily
a good idea. It is hard to be sure where they are going to land, and it
could be dangerous sitting under them as they fly overhead. -- RFC 1925
Igor Tandetnik
2010-03-01 12:36:40 UTC
Permalink
Post by Nobody
// Central function: Has 3 parameters, the first is sequence number
// This function does the real work.
int func(int seq, int para1,int para2)
{
// Some code
};
// "n" functions: Have 2 parameters. They call the central function.
int func0(int para1,int para2) { return func(0,para1,para2);};
int func1(int para1,int para2) { return func(1,para1,para2);};
int func2(int para1,int para2) { return func(2,para1,para2);};
int func3(int para1,int para2) { return func(3,para1,para2);};
Like I said, you can replace all these declarations with one:

template <int seq>
int func(int para1, int para2) { return func(seq, para1, para2); }
Post by Nobody
#define paster(n) int func##n(int para1,int para2) {return
func(n,para1,para2);}
paster(0);
paster(1);
paster(2);
paster(3);
These you wouldn't need at all.
Post by Nobody
When setting up the call back, I use another macro to fill an array with
MYPROC ProcArray[APPMAX] = {0};
#define PasteProcArray(n) ProcArray[n] = (MYPROC) func##n; i++
You'd still need this. Just replace func##n with func<n>
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Ulrich Eckhardt
2010-03-01 12:57:50 UTC
Permalink
Post by Nobody
int func(int seq, int para1,int para2)
{
// Some code
};
Just for the record, this isn't valid C or C++, as an empty statement (the
semicolon after the function definition) is not valid at namespace scope.
Ditto with the following code...
Post by Nobody
int func0(int para1,int para2) { return func(0,para1,para2);};
int func1(int para1,int para2) { return func(1,para1,para2);};
int func2(int para1,int para2) { return func(2,para1,para2);};
int func3(int para1,int para2) { return func(3,para1,para2);};
#define paster(n) int func##n(int para1,int para2) {return
func(n,para1,para2);}
paster(0);
paster(1);
paster(2);
paster(3);
This gets a price for ugliness and obfuscation. Generally accepted practice
is to use ALL_UPPERCASE names for macros and only for those.
Post by Nobody
When setting up the call back, I use another macro to fill an array with
MYPROC ProcArray[APPMAX] = {0};
#define PasteProcArray(n) ProcArray[n] = (MYPROC) func##n; i++
Sheesh! Why? Why do you have to cast the function pointer? In any case, you
can just replace this abomination with the not much more beautiful

#define PasteProcArray(n) ProcArray[n] = (MYPROC) func<n>; i++

and save yourself the whole "paster(1)..." code above, as the template is
automatically instantiated when used.
Post by Nobody
void InitProcArray(void)
{
int i=0;
PasteInitProcArray(0);
PasteInitProcArray(1);
PasteInitProcArray(2);
PasteInitProcArray(3);
if (i!=APPMAX) {
// Part of the array was not defined
MessageBox(NULL,_T("Size error in InitProcArray."), NULL, MB_OK);
}
}
Imagine you have one PasteInitProcArray() line twice. Your check would say
it's okay while one element is still missing. Actually, unless you need it
somewhere else, you don't even have to dynamically initialize the array:

MYPROC const ProcArray[] = {
&func<0>,
&func<1>,
&func<2>,
&func<3>,
};

void InitProcArray() {
assert((sizeof ProcArray)/(sizeof *ProcArray) == APPMAX);
// nothing left to do
}

BTW: Your code looks more or less like C, are you using C or C++? I ask
because without C++, any talk about templates is useless anyway.

Cheers!

Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
Nobody
2010-03-01 16:54:34 UTC
Permalink
Post by Ulrich Eckhardt
BTW: Your code looks more or less like C, are you using C or C++? I ask
because without C++, any talk about templates is useless anyway.
I am using C++. I didn't know about template expression parameters. I
assumed that even for templates that at least parameter types or their
numbers
Nobody
2010-03-01 16:59:31 UTC
Permalink
Post by Nobody
Post by Ulrich Eckhardt
BTW: Your code looks more or less like C, are you using C or C++? I ask
because without C++, any talk about templates is useless anyway.
I am using C++. I didn't know about template expression parameters. I
assumed that even for templates that at least parameter types or their
numbers
Oops, clicked send too soon. What I meant to say is that I thought that
templates must have at least a change in parameter types or their numbers
just like overloaded functions. But apparently this is not the case with
template functions. I will do more reading on that.

Thank you all for your comments...

Barry Schwarz
2010-02-28 23:43:16 UTC
Permalink
Post by Nobody
I am implementing a callback function for multiple callbacks, but the
callback function does not have a parameter such as a handle or number to
tell which callback the call is for. I have no control over it, so I can't
add my own parameters, so I have to provide different entry points that
calls a centralized routine with a sequence number. So I have functions like
int func0(int para1,int para2) { return func(0,para1,para2);};
int func1(int para1,int para2) { return func(1,para1,para2);};
int func2(int para1,int para2) { return func(2,para1,para2);};
int func3(int para1,int para2) { return func(3,para1,para2);};
...
I plan to use a macro like this to generate the above using the
#define paster( n ) int func##n(int para1,int para2) { return
func(##n,para1,para2);}
The preprocessor works on tokens. The purpose of the first ##
operator is to concatenate the literal func with the parameter n,
resulting in a single token (e.g., func1). What is the purpose of the
second ## operator? What would happen if you deleted it?
Post by Nobody
paster(0);
paster(1);
paster(2);
paster(3);
...
Is there a way to repeatedly call the macro a fixed number of times?
Not in C.
Post by Nobody
Something like #while or #for loop? Currently, I am using an Excel sheet to
= "paster(" & A1 & ");"
Cells A1 to Ann contain sequence numbers filled by Edit-->Fill-->Series, so
I only have to do one copy and paste.
I am using VC6 and 2003.
Thank you
--
Remove del for email
Nobody
2010-03-01 00:16:48 UTC
Permalink
Post by Barry Schwarz
Post by Nobody
I am implementing a callback function for multiple callbacks, but the
callback function does not have a parameter such as a handle or number to
tell which callback the call is for. I have no control over it, so I can't
add my own parameters, so I have to provide different entry points that
calls a centralized routine with a sequence number. So I have functions like
int func0(int para1,int para2) { return func(0,para1,para2);};
int func1(int para1,int para2) { return func(1,para1,para2);};
int func2(int para1,int para2) { return func(2,para1,para2);};
int func3(int para1,int para2) { return func(3,para1,para2);};
...
I plan to use a macro like this to generate the above using the
#define paster( n ) int func##n(int para1,int para2) { return
func(##n,para1,para2);}
The preprocessor works on tokens. The purpose of the first ##
operator is to concatenate the literal func with the parameter n,
resulting in a single token (e.g., func1). What is the purpose of the
second ## operator? What would happen if you deleted it?
I guess I should have used less confusing names. In the example, I have a
central function func() to be called by func0(), func1(), func2(), etc. This
central function func(), has an additional parameter "int seq", and these
"n" functions supply a sequential number to func(). This example maybe
illustrate it better:

// Central function: Has 3 parameters, the first is sequence number
int func(int seq, int para1,int para2)
{
// Some code
};

// "n" functions: Have 2 parameters

int func0(int para1,int para2)
{
return func(0,para1,para2);
};

int func1(int para1,int para2)
{
return func(1,para1,para2);
};
Nobody
2010-03-01 01:15:57 UTC
Permalink
Post by Nobody
// Central function: Has 3 parameters, the first is sequence number
In case I wasn't clear enough, the sequence parameter is used to lookup an
array of structures representing the corresponding callback.
Barry Schwarz
2010-03-01 03:26:19 UTC
Permalink
Post by Nobody
Post by Barry Schwarz
Post by Nobody
I am implementing a callback function for multiple callbacks, but the
callback function does not have a parameter such as a handle or number to
tell which callback the call is for. I have no control over it, so I can't
add my own parameters, so I have to provide different entry points that
calls a centralized routine with a sequence number. So I have functions like
int func0(int para1,int para2) { return func(0,para1,para2);};
int func1(int para1,int para2) { return func(1,para1,para2);};
int func2(int para1,int para2) { return func(2,para1,para2);};
int func3(int para1,int para2) { return func(3,para1,para2);};
...
I plan to use a macro like this to generate the above using the
#define paster( n ) int func##n(int para1,int para2) { return
func(##n,para1,para2);}
The preprocessor works on tokens. The purpose of the first ##
operator is to concatenate the literal func with the parameter n,
resulting in a single token (e.g., func1). What is the purpose of the
second ## operator? What would happen if you deleted it?
I guess I should have used less confusing names. In the example, I have a
central function func() to be called by func0(), func1(), func2(), etc.
That was perfectly clear. The point I was trying to get you to see is
that you are not creating a single token with the second ## operator.
It serves no purpose. The open parenthesis will always be a
stand-alone token. Removing the ## results in the exact same code
after substitution.
--
Remove del for email
Igor Tandetnik
2010-03-01 04:13:54 UTC
Permalink
Post by Barry Schwarz
Post by Nobody
#define paster( n ) int func##n(int para1,int para2) { return
func(##n,para1,para2);}
That was perfectly clear. The point I was trying to get you to see is
that you are not creating a single token with the second ## operator.
It serves no purpose. The open parenthesis will always be a
stand-alone token. Removing the ## results in the exact same code
after substitution.
In fact, (##n is an error, as it results in an illegal token (e.g. "(1" ). This only works because it is offset by a (well-known, long-standing) bug in MSVC compiler, whereby it combines the stream of tokens after macro substitution into a string and passes it back through the lexer, which reparses it into a new, possibly different, stream of tokens.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Nobody
2010-03-01 04:30:05 UTC
Permalink
Post by Barry Schwarz
That was perfectly clear. The point I was trying to get you to see is
that you are not creating a single token with the second ## operator.
It serves no purpose. The open parenthesis will always be a
stand-alone token. Removing the ## results in the exact same code
after substitution.
Okay, I see what you and others meant. Thank you to all who responded.
Tim Roberts
2010-03-01 01:48:27 UTC
Permalink
Post by Nobody
Is there a way to repeatedly call the macro a fixed number of times?
Something like #while or #for loop?
The short answer to your question is "no". You would need some external
tool do do this.
Interesting choice. I would have chosen Python, or awk, or Perl, or even a
batch file, but Excel would never have occurred to me.
--
Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
Continue reading on narkive:
Loading...