首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在宏中使用宏来转换宏的参数?

如何在宏中使用宏来转换宏的参数?
EN

Stack Overflow用户
提问于 2016-12-30 11:22:08
回答 1查看 264关注 0票数 1

我在我的项目中使用X宏,以便在名称列表需要对它们执行相同操作(例如创建、初始化、填充和销毁)的地方使用不重复我自己

由于我试图指定的数据涉及几个相同的可宏翻译(忽略参数、前缀和后缀),所以我决定通过将它们重写为广义元X宏来增强我原来的单曲X宏,从这些宏中可以定义多个导数最终用例拟合的X宏,使用解释元宏参数的转换宏:

代码语言:javascript
复制
// Meta-macros //

#define MAIN_WINDOW_TEXT_LAYERS_METAMACRO(macro, tr) \
  macro(tr(hour_layer)) \
  macro(tr(min_layer)) \
  macro(tr(date_layer))

#define MAIN_WINDOW_LAYERS_METAMACRO(macro, tr) \
  macro(tr(colon_layer)) \
  macro(tr(phone_batt_layer)) \
  macro(tr(watch_batt_layer))

#define GBITMAPS_WITH_RESOURCE_IDS_METAMACRO(macro, tr) \
  macro(tr(watch_icon, ICON_WATCH_6X11)) \
  macro(tr(watch_charging_icon, ICON_WATCH_CHARGING_6X11)) \
  macro(tr(phone_icon, ICON_PHONE_6X11)) \
  macro(tr(phone_charging_icon, ICON_PHONE_CHARGING_6X11))

#define GFONTS_WITH_RESOURCE_IDS_METAMACRO(macro, tr) \
  macro(tr(time_font, FONT_ARVO_BOLD_48)) \
  macro(tr(date_font, FONT_ARVO_BOLD_20))

// Transformation macros //

#define IDENTITY_MACRO(x) x
#define STATIC_PREFIX_MACRO(x) s_ ## x
#define STATIC_PREFIX_DISCARD_MACRO(x, _) s_ ## x
#define STATIC_PREFIX_RESOURCE_ID_PREFIX_MACRO(x, id) \
  s_ ## x, RESOURCE_ID_ ## s

// Derived X-Macros //

#define FOR_MAIN_WINDOW_STATIC_TEXT_LAYER_POINTERS(macro) \
  MAIN_WINDOW_TEXT_LAYERS_METAMACRO(macro, STATIC_PREFIX_MACRO)

#define FOR_MAIN_WINDOW_STATIC_LAYER_POINTERS(macro) \
  MAIN_WINDOW_LAYERS_METAMACRO(macro, STATIC_PREFIX_MACRO)

#define FOR_MAIN_WINDOW_LAYER_NAMES(macro) \
  MAIN_WINDOW_LAYERS_METAMACRO(macro, IDENTITY_MACRO)

#define FOR_STATIC_GFONTS(macro) \
  GFONTS_WITH_RESOURCE_IDS_METAMACRO(macro, STATIC_PREFIX_DISCARD_MACRO)

#define FOR_STATIC_GFONTS_WITH_RESOURCE_IDS(macro) \
  GFONTS_WITH_RESOURCE_IDS_METAMACRO(macro, STATIC_PREFIX_RESOURCE_ID_PREFIX_MACRO)

#define FOR_STATIC_GBITMAP_POINTERS_WITH_RESOURCE_IDS(macro) \
  GBITMAPS_WITH_RESOURCE_IDS_METAMACRO(macro, STATIC_PREFIX_RESOURCE_ID_PREFIX_MACRO)

#define FOR_STATIC_GBITMAP_POINTERS(macro) \
  GBITMAPS_WITH_RESOURCE_IDS_METAMACRO(macro, STATIC_PREFIX_DISCARD_MACRO)

在大多数用例中,这都是可行的:然而,在一些边缘案例中,我遇到了麻烦。首先,试图连接参数会导致转换宏的名称连接起来,而不是转换后的名称:

代码语言:javascript
复制
#define X(name) layer_set_update_proc(s_ ## name, name ## _update_proc);
FOR_MAIN_WINDOW_LAYER_NAMES(X)
#undef X

错误:函数“s_IDENTITY_MACRO”的隐式声明

其次,转换两个参数的宏不会被扩展--它们作为单个令牌(对转换宏的调用)传递给X

代码语言:javascript
复制
#define X(name, id) name = fonts_load_custom_font(resource_get_handle(id));
FOR_STATIC_GFONTS_WITH_RESOURCE_IDS(X)
#undef X

错误:宏"X“需要两个参数,但只有一个给定的错误:未知类型名称'X‘

代码语言:javascript
复制
#define X(name, id) name = gbitmap_create_with_resource(id);
FOR_STATIC_GBITMAP_POINTERS_WITH_RESOURCE_IDS(X)
#undef X

错误:宏"X“需要两个参数,但只有一个给定的错误:预期的'=','__attribute__‘之前的'X’

我怎样才能让这些东西按照我想要的方式工作呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-12-30 11:22:08

正如其他 堆栈 溢出 问题中提到的C预处理器,通过向宏引入另一层间接调用,可以避免第一个问题(宏的标识符被连接而不是其内容):

代码语言:javascript
复制
#define X_(name) layer_set_update_proc(s_ ## name, name ## _update_proc);
#define X(name) X_(name)
FOR_MAIN_WINDOW_LAYER_NAMES(X)
#undef X
#undef X_

第二个问题更隐秘,但它有一个类似的解决方案:另一层间接。这里的关键技巧是,与复制最终宏的签名不同,第一层必须使用单个参数传递到下一层,然后将其扩展到多个参数:

代码语言:javascript
复制
#define X_(name, id) name = fonts_load_custom_font(resource_get_handle(id));
#define X(args) X_(args)
FOR_STATIC_GFONTS_WITH_RESOURCE_IDS(X)
#undef X
#undef X_

当然,将这些类型的解决方案卸载到使用点,而不是在定义它们的点上修复它们,并不是一个健壮的工程,因此应该将这一层间接方向定义为元宏本身的一部分。

代码语言:javascript
复制
#define APPLY_MACRO(x, t) x(t)

#define MAIN_WINDOW_TEXT_LAYERS_METAMACRO(X, tr) \
  APPLY_MACRO(X,tr(hour_layer)) \
  APPLY_MACRO(X,tr(min_layer)) \
  APPLY_MACRO(X,tr(date_layer))

/* etc... */

但是,请注意,无论您选择用于APPLY_MACRO的任何令牌,与XX_这样的标识符不同,该标识符可以是#defined,并且在调用点附近立即使用#undef,这里使用的间接宏必须保持定义,只要可以使用这些宏本身(显然),因此应该选择一个不会引起与代码基的其他部分冲突的名称(即,不仅仅是X_)。甚至像APPLY_MACRO就像我以前在这里一样这样的东西也不是特别可取的:更大的项目(尤其是任何可能被重新分发以用于其他解决方案的代码)应该考虑在名称空间前缀中加上前缀,以限制其范围以避免干扰其他上下文(如这个SoftwareEngineering.se的答案中所描述的)。

然而,就我的目的而言,最终最终解决了这个问题,我重写了转换宏,将宏用于应用并使用转换后的参数调用它,简化了解释,并允许我完全重构上面描述的APPLY_MACRO宏。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41395464

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档