samedi 5 août 2017

Variadic macros: Reuse variadic arguments (Boost.Fusion)

I am working on a kind of "data-variable" framework. Here, structs are defined and adapted as Boost.Fusion sequences using the macro BOOST_FUSION_DEFINE_ASSOC_STRUCT.

Brief context:

To define two adapted structs foo and bar, I use:

#define VAR(VARNAME) vardefs::VARNAME
#define VAR_PARENTHESES(VARNAME) (vardefs)(VARNAME)

// ========================================================
#ifndef VARNAME_
#define VARNAME_ foo // <- Variable name
namespace VAR(VARNAME_)::keys{
    struct foo1;
    struct foo2;
    struct foo3;
}
namespace VAR(VARNAME_) { struct index; }

BOOST_FUSION_DEFINE_ASSOC_STRUCT(
    VAR_PARENTHESES(VARNAME_), type,
    (char, foo1, VAR(VARNAME_)::keys::foo1)
    (int, foo2, VAR(VARNAME_)::keys::foo2)
    (float, foo3, VAR(VARNAME_)::keys::foo3)
)
#endif
#undef VARNAME_
// --------------------------------------------------------

// ========================================================
#ifndef VARNAME_
#define VARNAME_ bar // <- Variable name
namespace VAR(VARNAME_)::keys{
    struct bar1;
    struct bar2;
}
namespace VAR(VARNAME_) { struct index; }

BOOST_FUSION_DEFINE_ASSOC_STRUCT(
    VAR_PARENTHESES(VARNAME_), type,
    (double, bar1, VAR(VARNAME_)::keys::bar1)
    (float, bar2, VAR(VARNAME_)::keys::bar2)
)
#endif
#undef VARNAME_
// --------------------------------------------------------

Now one can create instances of foo and bar by using:

VAR(foo)::type fooI;
VAR(bar)::type barI;

The associative keys can be used like this:

auto a = boost::fusion::at_key<VAR(foo)::keys::foo3>(fooI).
auto b = boost::fusion::at_key<VAR(bar)::keys::bar2>(barI).

This approach might be useful down the line.

Lastly, there are tags for the structs themselves:

VAR(bar)::index
VAR(foo)::index

I can use the later as type-keys in other Boost.Fusion sequences, e.g. boost::fusion::map.

Question:

Notice that, for each of the two structs, and since I am defining an associative sequence, I have to use the struct-field names (foo1, bar2, ...) three times each.

What I would like instead, is to define the above two structs as this:

// ========================================================
DEFINE_DATAVAR_STRUCT(
    foo,
    (char, foo1)
    (int, foo2)
    (float, foo3)
)
// --------------------------------------------------------

// ========================================================
DEFINE_DATAVAR_STRUCT(
    bar,
    (double, bar1)
    (float, bar2)
)
// --------------------------------------------------------

I only need to define the variadic macro DEFINE_DATAVAR_STRUCT. This is what I need help for.

I have looked at the Boost.PP library, but I am not doing very good progress here. Since the Boost.Fusion library is doing this already, there must be a way to achieve the same variadic functionality, similar to the BOOST_FUSION_DEFINE_ASSOC_STRUCT macro.

Looking in the header-files for Boost.Fusion I get no smarter really. I am also not sure how much Boost.Fusion relies on Boost.PP already to build the clever macros.

Compiler: Microsoft Visual Studio 2015 Update 3 (GCC, Clang are not options right now).

Boost: 1.64.0.

Aucun commentaire:

Enregistrer un commentaire