Boost logo

Boost Users :

Subject: [Boost-users] Preprocessor sequence of "pairs"
From: driscoll_at_[hidden]
Date: 2012-09-26 01:52:24


I have a question about the use of the preprocessor library. I'll describe
my ultimate goal in a moment, but I've simplified my first problem to the
following. Also, I know what I'm doing looks a lot at first glance like
Fusion's ADAPT_STRUCT, but I took a quick look at that documentation and I
don't think it matches. However, if you disagree with me and think it
does, or can suggest a totally different solution, feel free to describe
how.

== My problem ==

I don't like C's struct syntax, so I'm trying to define my own.
(</sarcasm> Really for purposes of this section I'm just doing this to
figure out all the steps I'll need.)

What I want to do is something like the following:

  #include <boost/preprocessor/seq/for_each.hpp>

  #define DEFINE_FIELD(r, os, field_pair) [....]

  #define DEFINE_STRUCT(struct_name, fields) \
      struct struct_name { \
          BOOST_PP_SEQ_FOR_EACH(DEFINE_FIELD, ~, fields) \
      }

  DEFINE_STRUCT(mystruct, (int, x)(int, y)(double, z))

but this doesn't work, because the sequence is made up of pairs instead of
single preprocessor arguments. (GCC complains about "macro
"BOOST_PP_SEQ_SIZE_0" passed 2 arguments, but takes just 1" and same for
PP_EXPR_IIF_0.)

I can get it to work by double-parenthesizing the stuff in the sequence
(saying "((int, x))((int, y))((double, z))") then defining DEFINE_FIELD as
follows:

  #define DEFINE_FIELD_REAL(type, name) type name;
  #define DEFINE_FIELD(r, os, field_pair) DEFINE_FIELD_REAL field_pair

but this is less than optimal. Is there a way that I can do this easily,
or would I effectively have to re-implement SEQ_FOR_EACH? (And how hard
would that be if it's necessary?)

== What I'm actually trying to do ==

What I'm actually doing is trying to write a macro that will define a
function like the following:

    DEFINE_SERIALIZED_STRUCT(mystruct, (int, x)(int, y)(double, z))
       |
       V
    struct mystruct {
        int x;
        int y;
        double z;
    };
    void serialize(ostream & os, mystruct const & s) {
        os << "x: " << s.x << "\n";
        os << "y: " << s.y << "\n";
        os << "z: " << s.z << "\n";
    }

(I didn't see a way to recover the field names from a Fusion-adapted
struct -- from what I can tell, it more just seems to be a way to iterate
over the fields.)


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