1

I'm working on generating some large static meta data structures right now, and would like to optimize the size of some the generated c++ files.

static constexpr MetaData* metaDataArray[] = {
  &MetaDataObject0,
  &MetaDataObject1,
  &MetaDataObject2,
  &MetaDataObject3,
  &MetaDataObject4,
  &MetaDataObject5,
  &MetaDataObject6,
  &MetaDataObject7,
  &MetaDataObject8,
  &MetaDataObject9,
  &MetaDataObject10,
  &MetaDataObject11,
  &MetaDataObject12,
  &MetaDataObject13,
  &MetaDataObject14,
  &MetaDataObject15,
  &MetaDataObject16,
  &MetaDataObject17,
  &MetaDataObject18,
  &MetaDataObject19,
  &MetaDataObject20
}

This is an example of an array that I would like to wrap into a macro. Preferrably something like this:

METADATA_ARRAY(MetaDataObject,20);

I realize this is probably quite tricky. I haven't really found a solution this problem yet, maybe it's not even possible to create a recursive macro that expands while keeping an index counter variable?

Maybe it's more feasible to aim for a macro more along these lines:

METADATA_ARRAY(MetaDataObject,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20);

I have found some references to variadic macros like this (along these lines: https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s).

This approach seems to be limited to 64 arguments though. Some of the arrays in our generated code have 3000+ elements. Is this possible to work around with some creative preprocessor black magic?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
TomasS
  • 21
  • 2
  • Does it have to be static? Populating a Singleton array with global constructors won't work? – jxh Oct 26 '15 at 12:00
  • Any reason why you can't use an union instead? The union containing either an array or the individual names. – Lundin Oct 26 '15 at 12:02
  • Could you elaborate on how I could use an union in this case? It's not obvious for me. – TomasS Oct 26 '15 at 14:47
  • Would you be willing to answer which compiler you are using? – jxh Oct 26 '15 at 15:53
  • gnu g++ 4.63 at the momemt, it's not a simple process to change to a newer version either (big organization with shared development environment setup). – TomasS Oct 27 '15 at 10:49
  • Windows or Linux, or other UNIX variant? ELF object format? – jxh Oct 27 '15 at 16:19

2 Answers2

1

You can achieve this using Boost Preprocessor:

#include <boost/preprocessor.hpp>

#define DECLARE_ENTRY(z, n, base_name) BOOST_PP_COMMA_IF(n) &base_name ## n

#define METADATA_ARRAY(type, var_name, base_name, count) static constexpr type* var_name[] = { \
        BOOST_PP_REPEAT(count, DECLARE_ENTRY, base_name) \
        }

demo:

METADATA_ARRAY(MetaData, metaDataArray, MetaDataObject, 5);

This results in:

static constexpr MetaData* metaDataArray[] = { &MetaDataObject0 , &MetaDataObject1 , &MetaDataObject2 , &MetaDataObject3 , &MetaDataObject4 };
m.s.
  • 16,063
  • 7
  • 53
  • 88
1

I'm adding an answer to my own question here.

The MAP macro described here does pretty much what I need for the second approach (https://github.com/swansontec/map-macro).

Using that it's easy to implement this:

METADATA_ARRAY(MetaDataObject,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20);

The first macro still seems a bit harder to accomplish.

TomasS
  • 21
  • 2