使用 X 宏的特定条目
Use specific entry of an X macro
我正在使用 X 宏来生成将 GPIO 设置为 0
或 1
的函数(我生成了大约 60 个函数来设置大约 30 个 GPIO)。这是一个例子(我刚刚写了这个例子,所以语法可能是错误的):
/* X(pin_name, pin_nb) */
#define CPLD_GPIOs \
X(Pin0, 0) \
X(Pin1, 1) \
X(Pin2, 2) \
X(Pin3, 3)
我生成了访问这些 GPIO 的函数:
#define X(pin_name, pin_nb) \
static void SetOn_GPIO##pin_name (void) { \
SetOn_GPIOpins(pin_nb);\
}
CPLD_GPIOs
#undef X
SetOff_GPIOXXX
个函数存在相同的过程。
有没有一种方法可以在程序的其他部分以 SetOn_GPIOPin2
的形式访问编译器上面生成的函数,而无需直接编写函数名称? (为了尽可能保持代码的全局性)
在预处理结束时,我们应该只从 X-Macro 生成 SetOn_GPIOPin2();
(而不是每个 X-macro 条目)。
预处理前:
void foo ()
{
/* some code */
/*
* Macro to generate the desired function.
* For e.g: SetOn_GPIOPin2();
*/
/* some code */
}
预处理后:
void foo ()
{
/* some code */
/* Function resulting of the pre-processing */
SetOn_GPIOPin2();
/* some code */
}
使用我们值得信赖的 Boost.Preprocessor 火箭发射器,这非常简单:
#include <boost/preprocessor/tuple/rem.hpp>
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/comparison/equal.hpp>
#define X_SELECT_PIN(pin_nb, selected_pin_nb, ...) \
BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_IF( \
BOOST_PP_EQUAL(pin_nb, selected_pin_nb), \
(__VA_ARGS__), \
() \
))
// Usage
#define X(pin_name, pin_nb)\
X_SELECT_PIN(pin_nb, 2, SetOn_GPIO##pin_name (void);)
CPLD_GPIOs
#undef X
这使用 BOOST_PP_IF
仅为所选图钉扩展您的图案。添加的括号和 BOOST_PP_TUPLE_REM_CTOR
是为了保护宏免受包含逗号的扩展的影响。
根据对该问题的评论,您的 objective 似乎是为了防止您的 X 宏被修改为生成 differently-named 函数的情况。如果是这样,那么我认为您是在为自己做不必要的工作:这些名称是否更改在您(和任何其他项目开发人员)的控制之下,并且您所关心的名称更改不会被忽视很长时间.所以不要改变它们。
但是,如果您决定走这条路,那么 不,没有办法让预处理器从宏的较大替换文本中提取由您的宏生成的函数名称。相反,您需要通过同一个宏将它们 注入 到 X 宏和您的其他代码中。像这样,也许:
/* X(pin_name, pin_nb) */
#define CPLD_GPIOs(gen) \
X(Pin0, 0, gen) \
X(Pin1, 1, gen) \
X(Pin2, 2, gen) \
X(Pin3, 3, gen)
// Generates the wanted function names:
#define GPIO_ON(pin_name, pin_nb) SetOn_GPIO##pin_name
#define X(pin_name, pin_nb, gen) \
static void gen(pin_name, pin_nb) (void) { \
SetOn_GPIOpins(pin_nb);\
}
CPLD_GPIOs
#undef X
// ...
void some_function(void) {
GPIO_ON(pin_name, pin_nb)();
}
但是请注意,虽然这项技术可能有其他应用,例如用同一组 X
宏生成多组函数,但它只是在特定的方面把罐头踢了下来objective 你描述的。您可以依靠 name-generator 宏来为函数声明和函数调用生成相同的名称,但是您仍然遇到可以修改 X
宏以生成具有不同名称的函数声明的问题。
我正在使用 X 宏来生成将 GPIO 设置为 0
或 1
的函数(我生成了大约 60 个函数来设置大约 30 个 GPIO)。这是一个例子(我刚刚写了这个例子,所以语法可能是错误的):
/* X(pin_name, pin_nb) */
#define CPLD_GPIOs \
X(Pin0, 0) \
X(Pin1, 1) \
X(Pin2, 2) \
X(Pin3, 3)
我生成了访问这些 GPIO 的函数:
#define X(pin_name, pin_nb) \
static void SetOn_GPIO##pin_name (void) { \
SetOn_GPIOpins(pin_nb);\
}
CPLD_GPIOs
#undef X
SetOff_GPIOXXX
个函数存在相同的过程。
有没有一种方法可以在程序的其他部分以 SetOn_GPIOPin2
的形式访问编译器上面生成的函数,而无需直接编写函数名称? (为了尽可能保持代码的全局性)
在预处理结束时,我们应该只从 X-Macro 生成 SetOn_GPIOPin2();
(而不是每个 X-macro 条目)。
预处理前:
void foo ()
{
/* some code */
/*
* Macro to generate the desired function.
* For e.g: SetOn_GPIOPin2();
*/
/* some code */
}
预处理后:
void foo ()
{
/* some code */
/* Function resulting of the pre-processing */
SetOn_GPIOPin2();
/* some code */
}
使用我们值得信赖的 Boost.Preprocessor 火箭发射器,这非常简单:
#include <boost/preprocessor/tuple/rem.hpp>
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/comparison/equal.hpp>
#define X_SELECT_PIN(pin_nb, selected_pin_nb, ...) \
BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_IF( \
BOOST_PP_EQUAL(pin_nb, selected_pin_nb), \
(__VA_ARGS__), \
() \
))
// Usage
#define X(pin_name, pin_nb)\
X_SELECT_PIN(pin_nb, 2, SetOn_GPIO##pin_name (void);)
CPLD_GPIOs
#undef X
这使用 BOOST_PP_IF
仅为所选图钉扩展您的图案。添加的括号和 BOOST_PP_TUPLE_REM_CTOR
是为了保护宏免受包含逗号的扩展的影响。
根据对该问题的评论,您的 objective 似乎是为了防止您的 X 宏被修改为生成 differently-named 函数的情况。如果是这样,那么我认为您是在为自己做不必要的工作:这些名称是否更改在您(和任何其他项目开发人员)的控制之下,并且您所关心的名称更改不会被忽视很长时间.所以不要改变它们。
但是,如果您决定走这条路,那么 不,没有办法让预处理器从宏的较大替换文本中提取由您的宏生成的函数名称。相反,您需要通过同一个宏将它们 注入 到 X 宏和您的其他代码中。像这样,也许:
/* X(pin_name, pin_nb) */
#define CPLD_GPIOs(gen) \
X(Pin0, 0, gen) \
X(Pin1, 1, gen) \
X(Pin2, 2, gen) \
X(Pin3, 3, gen)
// Generates the wanted function names:
#define GPIO_ON(pin_name, pin_nb) SetOn_GPIO##pin_name
#define X(pin_name, pin_nb, gen) \
static void gen(pin_name, pin_nb) (void) { \
SetOn_GPIOpins(pin_nb);\
}
CPLD_GPIOs
#undef X
// ...
void some_function(void) {
GPIO_ON(pin_name, pin_nb)();
}
但是请注意,虽然这项技术可能有其他应用,例如用同一组 X
宏生成多组函数,但它只是在特定的方面把罐头踢了下来objective 你描述的。您可以依靠 name-generator 宏来为函数声明和函数调用生成相同的名称,但是您仍然遇到可以修改 X
宏以生成具有不同名称的函数声明的问题。