美文网首页
C 宏 __COUNTER__

C 宏 __COUNTER__

作者: 飞天小小猫 | 来源:发表于2020-09-01 23:01 被阅读0次

    最近在看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__)

    相关文章

      网友评论

          本文标题:C 宏 __COUNTER__

          本文链接:https://www.haomeiwen.com/subject/wlwbsktx.html