motam
motam

Reputation: 747

Using boost preprocessor to stringize a tuple

I am beginner in using boost preprocessor. I want to use this library to generate a name from a tuple, for example I have a tuple like this (float, string, int, bool) and I want to construct something like this "Foo<float, string, int, bool>". I thought that it must be easy by using BOOST_PP_STRINGIZE, BOOST_PP_CAT and BOOST_PP_REPEAT but I unfortunately could not find a way to generate the string I wanted.

Please give me a suggestion about creating this string. Foo is a class name and tuple is generated automatically during preprocess.

Upvotes: 1

Views: 1649

Answers (1)

Qaz
Qaz

Reputation: 61930

You can use BOOST_PP_TUPLE_ENUM to get a comma-separated expansion of the tuple elements. You can then use #__VA_ARGS__ to stringize the resulting list. See it live:

#define STRINGIZE_ALL_I(...) #__VA_ARGS__
#define STRINGIZE_ALL(...) STRINGIZE_ALL_I(__VA_ARGS__)

#define MAKE_STRING(tuple) STRINGIZE_ALL(Foo<BOOST_PP_TUPLE_ENUM(tuple)>)

// "Foo<float, string, int, bool>"
MAKE_STRING((float, string, int, bool))

STRINGIZE_ALL_I exists for the same reason you have an extra layer in STRINGIZE and CONCAT - to evaluate macros before stringizing. In this case, you would get a string containing BOOST_PP_TUPLE_ENUM((…)) if you neglected to have two layers.

Note that STRINGIZE_ALL is called with the argument list Foo<float, string, int, bool>. That's four arguments, not one.


If variadic macros are not available (e.g., C++98), you can take advantage of the fact that "abc" "def" will be turned into "abcdef" by the compiler. See it live:

#define STRINGIZE_ALL_MACRO(s, state, x) state "," BOOST_PP_STRINGIZE(x)

#define STRINGIZE_ALL(seq)      \
    BOOST_PP_SEQ_FOLD_LEFT(     \
        STRINGIZE_ALL_MACRO,    \
        BOOST_PP_STRINGIZE(BOOST_PP_SEQ_HEAD(seq)), \
        BOOST_PP_SEQ_TAIL(seq)  \
    )

#define MAKE_STRING(size, tuple) \
    STRINGIZE_ALL(               \
        BOOST_PP_TUPLE_TO_SEQ(   \
            size,                \
            (Foo<BOOST_PP_TUPLE_ENUM(size, tuple)>) \
        )                        \
    )

// "Foo<float" "," "string" "," "int" "," "bool>"
MAKE_STRING(4, (float, string, int, bool))

For this version, your autogenerated tuple must generate a size as well. It's entirely possible to generate a tuple (size, (elems)) that you can use with this macro.

Upvotes: 3

Related Questions