我正在做一些预处理器元编程,并且需要一种将 f(a b)
转换为 g(a,b)
的方法,C++ 预处理器中的a
和b
是两个标记,因此似乎可以找到一种分离它们的方法。 然而,经过数小时的工作,仍然没有解决这个问题的方法。
欢迎任何第三方库,包括 boost::preprocessor
,只要这些库在预处理过程中工作即可。
此外,是否有一种分离任意标记的方法?例如const T&
应转换为const
,T
,&
我正在做一些预处理器元编程,并且需要一种将 f(a b)
转换为 g(a,b)
的方法,C++ 预处理器中的a
和b
是两个标记,因此似乎可以找到一种分离它们的方法。 然而,经过数小时的工作,仍然没有解决这个问题的方法。
欢迎任何第三方库,包括 boost::preprocessor
,只要这些库在预处理过程中工作即可。
此外,是否有一种分离任意标记的方法?例如const T&
应转换为const
,T
,&
这是不可能的。
对于有限数量的标记,这是可能的,但您必须拥有所有要处理的可能标记的字典。整个过程曾在Replace spaces with underscores in a macro? 中使用,在这里我将重写它,仅为了好玩。
通常,您可以使用前缀连接列表的前缀,例如WORD_##__VA_ARGS__
,其中__VA_ARGS__="a b c"
。然后,通过使用#define WORD_a a,
,您可以将前导单词与其余部分分开。对于每个标记重复此类过程,您可以创建一个单独的标记列表。
// dictionary of all words
#define WORD_
#define WORD_a a,
#define WORD_b b,
#define WORD_c c,
#define WORD_d d,
#define TOKENIZE_1(a) WORD_##a
#define TOKENIZE_2(a,...) a, TOKENIZE_1(__VA_ARGS__)
#define TOKENIZE_3(a,...) a, TOKENIZE_2(__VA_ARGS__)
#define TOKENIZE_4(a,...) a, TOKENIZE_3(__VA_ARGS__)
#define TOKENIZE_5(a,...) a, TOKENIZE_4(__VA_ARGS__)
#define TOKENIZE_N(_5,_4,_3,_2,_1,N,...) TOKENIZE##N
#define TOKENIZE(...) TOKENIZE_N(__VA_ARGS__,_5,_4,_3,_2,_1)(__VA_ARGS__)
#define REMOVELAST_1(a)
#define REMOVELAST_2(a,...) a
#define REMOVELAST_3(a,...) a, REMOVELAST_2(__VA_ARGS__)
#define REMOVELAST_4(a,...) a, REMOVELAST_3(__VA_ARGS__)
#define REMOVELAST_5(a,...) a, REMOVELAST_4(__VA_ARGS__)
#define REMOVELAST_N(_5,_4,_3,_2,_1,N,...) REMOVELAST##N
#define REMOVELAST(...) REMOVELAST_N(__VA_ARGS__,_5,_4,_3,_2,_1)(__VA_ARGS__)
#define SPACES_TO_ARGS(...) REMOVELAST(TOKENIZE(TOKENIZE(TOKENIZE(TOKENIZE(__VA_ARGS__)))))
#define f(spaceargs) g(SPACES_TO_ARGS(spaceargs))
f(a b) to g(a, b)
f(a b c) to g(a, b, c)
f(a b c d) to g(a, b, c, d)
#include <boost/preprocessor/variadic/to_seq.hpp>
#include <boost/preprocessor/control/while.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/to_tuple.hpp>
#include <boost/preprocessor/seq/pop_back.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/facilities/is_empty.hpp>
#include <boost/preprocessor/logical/not.hpp>
// dictionary of all words
#define WORD_
#define WORD_a a,
#define WORD_b b,
#define WORD_c c,
#define WORD_d d,
#define ADDWORD2(a) WORD_##a
#define ADDWORD(r, _, a) ADDWORD2(a)
#define TOKENIZE_OP(d, list) \
BOOST_PP_VARIADIC_TO_SEQ(BOOST_PP_SEQ_FOR_EACH(ADDWORD, _, list))
#define SEQ_LAST(state) \
BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(state)), state)
#define TOKENIZE_PRED(d, state) \
BOOST_PP_NOT(BOOST_PP_IS_EMPTY(SEQ_LAST(state)))
#define SPACES_TO_ARGS(...) \
BOOST_PP_SEQ_TO_TUPLE(BOOST_PP_SEQ_POP_BACK( \
BOOST_PP_WHILE(TOKENIZE_PRED, TOKENIZE_OP, (__VA_ARGS__)) \
))
#define f(spaceargs) g SPACES_TO_ARGS(spaceargs)
f(a b)
f(a b c)
f(a b c d)
const T&
已经是三个标记了。它们怎么能更分离呢?预处理器中唯一模糊支持空格的操作是串化运算符 (#
) ,一旦完成它,空格就不再相关了。 - riciGEN(f, (int a,_), void, ({ return a;}))
应该扩展为template<typename T0> auto f (int a, T0) -> void { return a; }
。对于简单的_
,我的模式匹配代码可以很好地工作,但它无法处理像(int a, const _)
这样的参数列表,因此我正在寻找一种将_
与const _
分开的方法。 - lz96#define a a,
可以实现这个功能,但这可能不是你想要的 ;) - Potatoswatter