【问题标题】:Pass a token with "::" as argument to C/C++ macro将带有“::”的标记作为参数传递给 C/C++ 宏
【发布时间】:2016-02-12 03:20:17
【问题描述】:

假设我有两个具有相同成员变量但“前缀”不同的结构。一个在命名空间中,另一个以某个标记为前缀。

我想编写一个宏来对这些接受不同前缀作为输入的结构执行相同的操作。我试过这个:

#include <cstdio>

struct A__foo_
{
  int bar;
} typedef A__foo;

namespace B {
  struct foo {
    int bar;
  };
}

#define GET_BAR(Prefix)\
  { \
    Prefix ## foo my_foo;\
    printf("Bar is: %d", my_foo.bar);\
  }

int main(int argc, char ** argv) {
  GET_BAR(A__);
  GET_BAR(B::);
}

我得到这个编译器错误:

macros_example.cpp:22:7: 错误:粘贴形成的 '::foo',一个无效的预处理令牌 GET_BAR(B::);

有没有办法以优雅的方式重写此宏以接受两个输入并将它们与“foo”连接起来?我尝试通过连接“B”和双冒号来预处理 B::。我也尝试将Prefix ## foo 更改为简单的Prefix foo,但随后调用GET_BAR(A__) 会导致编译错误。

【问题讨论】:

    标签: c++ namespaces macros c-preprocessor


    【解决方案1】:

    很难理解我脱离上下文提出的解决方案,但这里是:

    #define CONCATENATE_A(X) A__ ## X
    #define CONCATENATE_B(X) B:: X
    
    #define GET_BAR(CONCATENATE)\
      { \
        CONCATENATE(foo) my_foo;\
        printf("Bar is: %d", my_foo.bar);\
      }
    
    int main(int argc, char ** argv) {
      GET_BAR(CONCATENATE_A);
      GET_BAR(CONCATENATE_B);
    }
    

    基本上,传递连接函数而不是标记本身。

    【讨论】:

      【解决方案2】:

      ::foo 不是预处理令牌。 ::foo 是令牌。令牌粘贴操作符用于在其他令牌的基础上形成一个新令牌。

      对于这两个用例,您必须使用不同的宏。

      【讨论】:

      • > 对于这两个用例,您必须使用不同的宏。不同的?比如什么?
      最近更新 更多