Pre-Processing loop

I

Itay

Hi all ,

Suppose i have structurs defines as follows :
struct S1
{
int n1 ;
int n2 ;
int n3 ;
};

struct S2
{
int i1 ;
int i2 ;
int i3 ;
};

i need to copy each member from S1 to it's corresponding in S2 something like:

s1.n1 = s2.i1 ;
s1.n2 = s2.i2 ;
s1.n3 = s2.i3 ;

is there a way to create those line in a macro ???
what i need is something like :

#define COPY(n)
#if ( n != 0 )
copy n to i\
COPY(n-1) \ reccursive call
#endif

BTW : i'm using vc++ compiler (and preprocessor).

Thanks.
 
V

Victor Bazarov

Itay said:
Suppose i have structurs defines as follows :
struct S1
{
int n1 ;
int n2 ;
int n3 ;
};

struct S2
{
int i1 ;
int i2 ;
int i3 ;
};

i need to copy each member from S1 to it's corresponding in S2 something like:

s1.n1 = s2.i1 ;
s1.n2 = s2.i2 ;
s1.n3 = s2.i3 ;

is there a way to create those line in a macro ???
what i need is something like :

#define COPY(n)
#if ( n != 0 )
copy n to i\
COPY(n-1) \ reccursive call
#endif

If the layouts of the two structures are really so much the same,
why don't you use some kind of low-end memcpy routine? If the
layouts are not the same (as to prohibit the use of memcpy), why
not have a simple function that would do the copying for you

void copyints(S1& s1, S2 const& s2) {
s1.n1 = s2.i1 ;
s1.n2 = s2.i2 ;
s1.n3 = s2.i3 ;
}

? Why do you need to involve a preprocessor at all?

And, no, AFAIK, there are no means in C++ preprocessor to make
recursive macro expansions that could stop based on its argument
value.

Victor
 
J

Jeff F

Victor Bazarov said:
If the layouts of the two structures are really so much the same,
why don't you use some kind of low-end memcpy routine? If the
layouts are not the same (as to prohibit the use of memcpy), why
not have a simple function that would do the copying for you

void copyints(S1& s1, S2 const& s2) {
s1.n1 = s2.i1 ;
s1.n2 = s2.i2 ;
s1.n3 = s2.i3 ;
}

? Why do you need to involve a preprocessor at all?

And, no, AFAIK, there are no means in C++ preprocessor to make
recursive macro expansions that could stop based on its argument
value.

See the Boost Preprocessor Library at www.boost.org.

Jeff
 
P

Paul Mensonides

Victor said:
[...]
See the Boost Preprocessor Library at www.boost.org.

So, what's the solution? Post it, don't tease.

#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>

#define COPY_M(z, v, _) \
s1.BOOST_PP_CAT(n, BOOST_PP_INC(v)) \
= s2.BOOST_PP_CAT(i, BOOST_PP_INC(v)); \
/**/
#define COPY(n) BOOST_PP_REPEAT(n, COPY_M, ~)

COPY(3)

Regards,
Paul Mensonides
 
V

Victor Bazarov

Paul Mensonides said:
Victor said:
[...]
And, no, AFAIK, there are no means in C++ preprocessor to make
recursive macro expansions that could stop based on its argument
value.

See the Boost Preprocessor Library at www.boost.org.

So, what's the solution? Post it, don't tease.

#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>

#define COPY_M(z, v, _) \
s1.BOOST_PP_CAT(n, BOOST_PP_INC(v)) \
= s2.BOOST_PP_CAT(i, BOOST_PP_INC(v)); \
/**/
#define COPY(n) BOOST_PP_REPEAT(n, COPY_M, ~)

COPY(3)


Interesting. Only I can't use it. My compiler doesn't come with
those headers. Any solution in terms of standard C++?

Thanks.
 
P

Paul Mensonides

Interesting. Only I can't use it. My compiler doesn't come with
those headers. Any solution in terms of standard C++?

Certainly. The following implements the scaffolding required to implement a
generic repetition construct, a generic repetititon construct, and then the use
of that construct to generate the assignments.

This is "standard C++" which means that it won't work on most preprocessors
(e.g. not VC, not EDG, not Sun, not IBM, not Borland, and not Metrowerks).
Preprocessors that are compliant enough include Wave, GCC, Borland's free
command line preprocessor (the non-integrated one), and probably Metrowerks' new
preprocessor available with their version 9 Macintosh compiler.

The following implementation can only repeat something nine times. In order to
increase that limit, you need to increase the number of DEC_x macros and the
number of EXPR_x macros such that they go as high as necessary. However, the
construct is multidimensional, and the invocations of the external macros are
trampolined. In other words, the first dimension can repeat nine elements, the
second dimension can repeat eight elements, the third dimension can repeat seven
elements, and so on.

// concatenation
#define CAT(a, b) PRIMITIVE_CAT(a, b)
#define PRIMITIVE_CAT(a, b) a ## b

// binary intermediate split
#define SPLIT(i, im) PRIMITIVE_CAT(SPLIT_, i)(im)
#define SPLIT_0(a, b) a
#define SPLIT_1(a, b) b

// saturating increment and decrement
#define DEC(x) SPLIT(0, PRIMITIVE_CAT(DEC_, x))
#define INC(x) SPLIT(1, PRIMITIVE_CAT(DEC_, x))

#define DEC_0 0, 1
#define DEC_1 0, 2
#define DEC_2 1, 3
#define DEC_3 2, 4
#define DEC_4 3, 5
#define DEC_5 4, 6
#define DEC_6 5, 7
#define DEC_7 6, 8
#define DEC_8 7, 9
#define DEC_9 8, 9

// bit complement
#define COMPL(bit) PRIMITIVE_CAT(COMPL_, bit)
#define COMPL_0 1
#define COMPL_1 0

// nullary parentheses detection
#define IS_NULLARY(x) SPLIT(0, CAT(IS_NULLARY_R_, IS_NULLARY_C x))
#define IS_NULLARY_C() 1
#define IS_NULLARY_R_1 1, ~
#define IS_NULLARY_R_IS_NULLARY_C 0, ~

// boolean conversion
#define BOOL(x) COMPL(IS_NULLARY(PRIMITIVE_CAT(BOOL_, x)))
#define BOOL_0 ()

// recursion backend
#define EXPR(s) PRIMITIVE_CAT(EXPR_, s)
#define EXPR_0(x) x
#define EXPR_1(x) x
#define EXPR_2(x) x
#define EXPR_3(x) x
#define EXPR_4(x) x
#define EXPR_5(x) x
#define EXPR_6(x) x
#define EXPR_7(x) x
#define EXPR_8(x) x
#define EXPR_9(x) x

// bit-oriented if control structure
#define IIF(bit) PRIMITIVE_CAT(IIF_, bit)
#define IIF_0(t, f) f
#define IIF_1(t, f) t

// number-oriented if control structure
#define IF(cond) IIF(BOOL(cond))

// emptiness abstraction
#define EMPTY()

// 1x and 2x deferral macros
#define DEFER(macro) macro EMPTY()
#define OBSTRUCT() DEFER(EMPTY)()

// argument list eater
#define EAT(size) PRIMITIVE_CAT(EAT_, size)
#define EAT_0()
#define EAT_1(a)
#define EAT_2(a, b)
#define EAT_3(a, b, c)
#define EAT_4(a, b, c, d)
#define EAT_5(a, b, c, d, e)
#define EAT_6(a, b, c, d, e, f)

// comma abstractions
#define COMMA() ,
#define COMMA_IF(n) IF(n)(COMMA, EMPTY)()

// repetition construct
#define REPEAT(s, count, macro, data) \
EXPR(s)(REPEAT_I(INC(s), INC(s), count, macro, data)) \
/**/
#define REPEAT_INDIRECT() REPEAT_I
#define REPEAT_I(s, o, count, macro, data) \
IF(count)(REPEAT_II, EAT(6))(OBSTRUCT(), s, o, DEC(count), macro, data) \
/**/
#define REPEAT_II(_, s, o, count, macro, data) \
EXPR(s) _(REPEAT_INDIRECT _()( \
INC(s), o, count, macro, data \
)) \
EXPR OBSTRUCT()(o)(macro OBSTRUCT()(o, count, data)) \
/**/

// original example
#define COPY_M(s, v, _) s1.CAT(n, INC(v)) = s2.CAT(i, INC(v));
#define COPY(n) EXPR(0)(REPEAT(0, n, COPY_M, ~))

COPY(3)

// multidimensional example (template template parameters)
#define FIXED(s, n, text) COMMA_IF(n) text
#define TTP(s, n, _) \
COMMA_IF(n) template<REPEAT(s, INC(n), FIXED, class)> class T ## n \
/**/
#define TEMPLATE_TEMPLATE(n) EXPR(0)(REPEAT(0, n, TTP, ~))

TEMPLATE_TEMPLATE(3)

Boost.Preprocessor cannot get away with this level of abstraction because it
requires a strictly conforming preprocessor. This is similar to the way Chaos
generalizes recursion. Most of the above are general purpose library facilities
(rather than the means to implement the trivial example in question). Hence, it
is better to just get Boost (though I realize that you were just being strictly
topical).

Regards,
Paul Mensonides
 
I

Itay

Whhoow ,
Thanks for the replies.
Actually i was looking for a much simplier solution.
I'm not familar with the boost libraries though i heard it good.
Can someone apply a simple solution to the simple sample i posted ???

Thanks.
 
D

Dan Cernat

Whhoow ,
Thanks for the replies.
Actually i was looking for a much simplier solution.
I'm not familar with the boost libraries though i heard it good.
Can someone apply a simple solution to the simple sample i posted ???

Thanks.

Victor posted a simple solution.
 
P

Paul Mensonides

Dan said:
(e-mail address removed) (Itay) wrote in message


Victor posted a simple solution.

Yes, Victor's solution is the way to go in this case.

Regards,
Paul Mensonides
 

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
474,146
Messages
2,570,832
Members
47,374
Latest member
anuragag27

Latest Threads

Top