如何解析C++预处理器中用空格分隔的标记?

dwbf0jvd  于 2023-04-08  发布在  其他
关注(0)|答案(1)|浏览(103)

我正在做一些预处理器元编程,我需要一种方法在C++预处理器中将f(a b)转换为g(a,b)。由于abC++中的两个标记,因此似乎可以找到一种方法将它们分开。然而,经过数小时的工作,仍然没有解决这个问题。
任何包括boost::preprocessor的第三方库都是受欢迎的,因为这些库在预处理过程中工作。
此外,是否有任何方法可以分离任意令牌?例如,const T&应该转换为constT&

0ve6wy6x

0ve6wy6x1#

这不可能。
对于有限数量的标记,这是可能的,但你必须有一个字典的所有可能的标记,你想处理。整个过程中使用的替换空格与下划线在一个宏?在这里,我将重写它没有寻找只是为了好玩。
通常,您可以将列表的前面与前缀连接起来,如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)

此外,是否有任何方法可以分离任意令牌?
不,这不可能。
任何第三方库,包括boost::preprocessor都是受欢迎的,因为这些库在预处理过程中工作。
我使用BOOST_PP_WHILE使它对任意数量的参数(直到boost限制)更加抽象。

#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)

相关问题