C 宏 __COUNTER__

最近在看apollo的代码,在class loader模块部分有个__COUNTER__宏:

#define CLASS_LOADER_REGISTER_CLASS_INTERNAL(Derived, Base, UniqueID)     \
  namespace {                                                             \
  struct ProxyType##UniqueID {                                            \
    ProxyType##UniqueID() {                                               \
      apollo::cyber::class_loader::utility::RegisterClass<Derived, Base>( \
          #Derived, #Base);                                               \
    }                                                                     \
  };                                                                      \
  static ProxyType##UniqueID g_register_class_##UniqueID;                 \
  }

#define CLASS_LOADER_REGISTER_CLASS_INTERNAL_1(Derived, Base, UniqueID) \
  CLASS_LOADER_REGISTER_CLASS_INTERNAL(Derived, Base, UniqueID)

// register class macro
#define CLASS_LOADER_REGISTER_CLASS(Derived, Base) \
  CLASS_LOADER_REGISTER_CLASS_INTERNAL_1(Derived, Base, __COUNTER__)

看起来是当作UniqueID来用。原理呢?
预定义宏 ( Predefined Macros ) 的其中之一,这是编译器拓展,gcc, vs 都支援。

根据 GCC.GNU 的文档

This macro expands to sequential integral values starting from 0\. 
In conjunction with the ## operator, this provides a convenient means to generate unique identifiers. 
Care must be taken to ensure that __COUNTER__ is not expanded prior to inclusion of precompiled headers which use it. 
Otherwise, the precompiled headers will not be used.

__COUNTER__ 是一个计数器,

会从 0 开始计数,然后每次调用加 1,即:

__COUNTER__  // 0
__COUNTER__  // 1
__COUNTER__  // 2

如何实现呢?

通常配合 ## 使用,用于构建唯一的标识符(identifiers)。
做法其实很简单,把任意一个标识符与 COUNTER 合并就可以了。

最普遍的做法是,加一个中间层。
合并用的宏:
#define merge_body(a, b) a ## b //合并用的主体
因為 ## 的特性 ( 阻止另一个宏的展开 ),需要中间层:
#define merge(a, b) merge_body(a, b) //中间层
把标识符与 __COUNTER__合并:
#define uniqueVarName(name) merge(name, __COUNTER__)
uniqueVarName() 就可以建立唯一的变数名称了。
Apollo就是使用了这种方法。

第二种方法,使用延迟展开的左括弧:
#define leftBracket (
使用这个的话,就可以把中间层去掉,然后 uniqueVarName() 变成这样:
#define uniqueVarName(name) merge_body leftBracket name, __COUNTER__)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容