使用boost预处理器对元组进行字符串化

时间:2016-01-24 08:16:38

标签: c++ boost boost-preprocessor

我是使用boost预处理器的初学者。我想使用这个库从元组生成一个名称,例如我有一个像(float, string, int, bool)这样的元组,我想构造像这样的"Foo<float, string, int, bool>"。我认为使用BOOST_PP_STRINGIZEBOOST_PP_CATBOOST_PP_REPEAT一定很容易,但遗憾的是我找不到生成我想要的字符串的方法。

请给我一个关于创建此字符串的建议。 Foo是一个类名,在预处理过程中会自动生成元组。

1 个答案:

答案 0 :(得分:2)

您可以使用BOOST_PP_TUPLE_ENUM来获取元组元素的逗号分隔扩展。然后,您可以使用#__VA_ARGS__对结果列表进行字符串化。 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的存在与您在STRINGIZECONCAT中有额外图层的原因相同 - 在字符串化之前评估宏。在这种情况下,如果您忽略了两层,则会得到一个包含BOOST_PP_TUPLE_ENUM((…))的字符串。

请注意,使用参数列表STRINGIZE_ALLFoo<floatstringint调用bool>。这是四个论点,而不是一个。

如果可变参数宏不可用(例如,C ++ 98),则可以利用编译器将"abc" "def"转换为"abcdef"这一事实。 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))

对于此版本,您自动生成的元组也必须生成大小。完全可以生成可以与此宏一起使用的元组(size, (elems))