每个参数的可变宏替换是否可行?

时间:2014-10-20 21:05:06

标签: c++ c++11 c-preprocessor variadic-macros

我现在阅读了很多关于可变参数宏的问题,但似乎并没有人回答最简单的问题:

#define IDENTITY(x) x
#define IDENTITY_FOR_ALL(...) ???

有没有办法让IDENTITY_FOR_ALL扩展到IDENTITY(X)所有参数?是否也可以使用任意数量的参数?

2 个答案:

答案 0 :(得分:3)

对于可变参数宏没有包扩展,因为存在可变参数模板。

您可以使用Boost.Preprocessor(或其方法)。

如果您不想在元素之间使用逗号,请使用

#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>

#define ID_OP(_, func, elem) func(elem)
#define APPLY_TO_ALL(func, ...)                \
    BOOST_PP_SEQ_FOR_EACH(                     \
        ID_OP, func,                           \
        BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)  \
    )

// example call:

#define SomeTransformation(x) #x // stringize the argument

APPLY_TO_ALL(SomeTransformation, 1, 2, 3) // expands to "1" "2" "3"

Demo。 用逗号:

#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/transform.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>

#define ID_OP(_, func, elem) func(elem)
#define APPLY_TO_ALL(func, ...)               \
    BOOST_PP_SEQ_ENUM(                        \
    BOOST_PP_SEQ_TRANSFORM(                   \
        ID_OP, func,                          \
        BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) \
    ))

// example call:

APPLY_TO_ALL(SomeTransformation, 1, 2, 3) // expands to "1", "2", "3"

Demo。 使用g++ -std=c++11 -E -P file检查预处理器输出。

答案 1 :(得分:1)

假设您需要PP解决方案,可以使用BOOST_PP_REPEAT

//invoke IDENTITY_FOR_ALL_MACRO with each index and the given tuple
#define IDENTITY_FOR_ALL(...)                   \
    BOOST_PP_REPEAT(                            \
        BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),    \
        IDENTITY_FOR_ALL_MACRO,                 \
        BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__) \
    )

//use the index to access the right element of the passed tuple
#define IDENTITY_FOR_ALL_MACRO(z, n, data) \
    IDENTITY(BOOST_PP_TUPLE_ELEM(n, data))

IDENTITY_FOR_ALL(abc, 123, "woopee")
//translated to abc 123 "woopee"

如果您需要使用几个不同的宏而不仅仅{{1}执行此操作,那么将此变为一个更通用的宏,将宏调用以及单个参数列表逐个传递将会非常简单明了。 }。

我不是100%肯定你的意思是任意数量的参数,但如果你想一次用两个参数而不是一个参数调用IDENTITY,你可以改变底部的宏来使用{ {1}}和IDENTITY访问元组的“2n”和“2n + 1”元素,然后在BOOST_PP_MUL调用中调用宏的次数只有一半。