使用 boost 预处理器对元组进行字符串化
Using boost preprocessor to stringize a tuple
我是使用 boost 预处理器的初学者。我想使用这个库从元组中生成一个名称,例如我有一个像这样的元组 (float, string, int, bool)
,我想构造像这样的东西 "Foo<float, string, int, bool>"
。我认为使用 BOOST_PP_STRINGIZE
、BOOST_PP_CAT
和 BOOST_PP_REPEAT
一定很容易,但不幸的是我找不到生成我想要的字符串的方法。
请给我一个关于创建这个字符串的建议。 Foo
是一个 class 名称,元组在预处理期间自动生成。
您可以使用 BOOST_PP_TUPLE_ENUM
获得元组元素的 comma-separated 扩展。然后,您可以使用 #__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
存在的原因与您在 STRINGIZE
和 CONCAT
中有一个额外层的原因相同 - 在字符串化之前评估宏。在这种情况下,如果您忽略了两层,您将得到一个包含 BOOST_PP_TUPLE_ENUM((…))
的字符串。
请注意,STRINGIZE_ALL
是使用参数列表 Foo<float
、string
、int
、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))
。
我是使用 boost 预处理器的初学者。我想使用这个库从元组中生成一个名称,例如我有一个像这样的元组 (float, string, int, bool)
,我想构造像这样的东西 "Foo<float, string, int, bool>"
。我认为使用 BOOST_PP_STRINGIZE
、BOOST_PP_CAT
和 BOOST_PP_REPEAT
一定很容易,但不幸的是我找不到生成我想要的字符串的方法。
请给我一个关于创建这个字符串的建议。 Foo
是一个 class 名称,元组在预处理期间自动生成。
您可以使用 BOOST_PP_TUPLE_ENUM
获得元组元素的 comma-separated 扩展。然后,您可以使用 #__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
存在的原因与您在 STRINGIZE
和 CONCAT
中有一个额外层的原因相同 - 在字符串化之前评估宏。在这种情况下,如果您忽略了两层,您将得到一个包含 BOOST_PP_TUPLE_ENUM((…))
的字符串。
请注意,STRINGIZE_ALL
是使用参数列表 Foo<float
、string
、int
、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))
。