代码之家  ›  专栏  ›  技术社区  ›  Barry

在MSVC中处理宏中的额外括号

  •  4
  • Barry  · 技术社区  · 6 年前

    有些情况下,您需要(a)有一个宏,该宏(b)在(c)语言不允许使用括号的情况下将其参数之一括起来。

    简单示例:

    #define MAKE_STRUCT(name, base) struct name : base { }
    
    struct X { };
    MAKE_STRUCT(Y, X);   // ok
    MAKE_STRUCT(Z, (X)); // error
    

    这是一个错误,因为我们需要一个类型名 ( ecatmur 通过利用 另外 允许使用一组额外括号的语言部分:

    template<typename T> struct argument_type;
    template<typename T, typename U> struct argument_type<T(U)> { typedef U type; };
    
    #define MAKE_STRUCT(name, base) struct name : argument_type<void(base)>::type { }
    
    struct X { };
    MAKE_STRUCT(Y, X);   // ok
    MAKE_STRUCT(Z, (X)); // ok
    

    这可以在gcc和clang上编译,但不能在MSVC上编译。是否有特定于MSVC的技巧来允许使用括号,或者有不同的技巧可以在所有三个编译器上运行?

    这个可能带括号的类型是通过几个宏传递的,所以我不确定其他答案是否适用(这里的上下文试图使用Catch2将多个模板参数传递给一个fixture TEST_CASE_METHOD() )。

    2 回复  |  直到 6 年前
        1
  •  4
  •   user7860670    6 年前

    因此,我采用了以下纯预处理器解决方案,仅当括号存在时才会去除括号。似乎适用于vc++、g++和clang++,并且可能可以修改以处理多个级别的括号。

    #define MAKE_STRUCT(name, base) struct name: EXPAND1(DEF base) {}
    #define EXPAND1(param) EXPAND2(param)
    #define EXPAND2(param) NO## param
    #define DEF(param) DEF param
    #define NODEF
    
    struct X { };
    MAKE_STRUCT(Y, X);   // ok
    MAKE_STRUCT(Z, (X)); // ok
    

    online compiler

        2
  •  -1
  •   SergeyA    6 年前

    这不是一个很好的解决方案,但如果可以修补所讨论的结构,并且只支持一级括号,那么这似乎是可行的:

    struct tag {};
    
    #define MAKE_STRUCT(name, base) struct name : \
      decltype(base(tag{})) { };
    
    struct X {
         X(tag );
         X() = default;
    };
    
    MAKE_STRUCT(Y, X);   // ok
    MAKE_STRUCT(Z, (X)); // ok