Boost logo

Boost Users :

Subject: [Boost-users] preprocessor metaprogramming question
From: Nathan Ridge (zeratul976_at_[hidden])
Date: 2010-06-20 19:51:39


Hello,

 

Here's a question for the preprocessor metaprogramming experts out there.

 

I have some classes that need to have write() methods that look like this:

 

template <typename output>

bool write(output& out) const

{

    return utils::write(out, member_1) &&

           utils::write(out, member_2) &&

           ...

           utils::write(out, member_n);

}

 

where member_1, member_2, ..., member_n are the member variables of the class.

 

(These write() methods are used as part of a serialization framework).

 

Since I have quite a few classes that need write() methods that look like this,

and the structure of each write() method is uniform (the only thing that varies

is the names of the class members), I figured that it would be neat to somehow

generate the code for these write() methods.

 

What I came up with is macros that look like this:

 

#define MEMBERS1(m1) \
    template <typename output> \
    bool write(output& out) const \
    { \
        return utils::write(out, m1); \
    }

#define MEMBERS2(m1, m2) \
    template <typename output> \
    bool write(output& out) const \
    { \
        return utils::write(out, m1) && \
               utils::write(out, m2); \
    }

 

// and so on for MEMBERS3, MEMBERS4, etc.

 

Then, instead of declaring and defining the write() methods explicilty,

I would just call the appropriate MEMBERS# macro in the class definition,

e.g. for a class with 3 members named a, b, and c, I'd write

MEMBERS3(a, b, c) in the class definition.

 

While this is definitely an improvement over writing the write() methods

explicitly for each class, there are two issues with it:

 

1) The number of lines of code needed to write the macro definitions

is quadratic in the maximum number of parameters supported.

It would be nice if it could be constant instead.

 

2) The user of the macros needs to match the macro name to the number

of member variables in the class, and to change the macro name whenever

the number of member variables changes.

 

I'm wondering if there is a way to improve on this generation scheme

that solves one or both of these issues.

 

If I were allowed to use C++0x, I could have a variadic macro MEMBERS(...)

and inside it pass the parameters to a variadic template function which

unpacks its parameters and calls utils::write() on each. This would solve

both issues. Unfortunately, however, I am not allowed to use C++0x features,

since our code needs to be able to compile on our servers, which run Ubuntu 8.04,

which runs g++ 4.2, which does not support C++0x features.

 

So I thought I'd turn to some more preprocessor magic to solve these issues.

I looked at examples in Boost.Preprocessor that generated repetitive code

using preprocessor metaprogramming. However, all the examples there

generated repetitive *code*, whereas what I seem to need is to be able

to generate repetitive *macro definitions*. Is there a way to do that?

If not, can anyone recommend other ways of improving the way I generate

the code for the write() functions?

 

Thanks in advance,

Nate.
                                               
_________________________________________________________________
Learn more ways to connect with your buddies now
http://go.microsoft.com/?linkid=9734388



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net