C++;预处理器不知道模板参数? < P> >,如果一个带有多个参数的模板实例化作为一个参数传递给宏,C++预处理器就失败了。p>

C++;预处理器不知道模板参数? < P> >,如果一个带有多个参数的模板实例化作为一个参数传递给宏,C++预处理器就失败了。p>,c++,templates,parameters,arguments,c-preprocessor,C++,Templates,Parameters,Arguments,C Preprocessor,请参见下面的示例 #include <stdio.h> #define FOO(v) printf("%d\n",v::val()) template<int N> struct bar { static int val() { return N; } }; template<int N, int M> struct baz { static int val() { return N+M; } }; int main() { pr

请参见下面的示例

#include <stdio.h>

#define FOO(v) printf("%d\n",v::val())

template<int N>
struct bar {
    static int val() { return N; }
};
template<int N, int M>
struct baz {
    static int val() { return N+M; }
};

int main() {
    printf("%d\n",bar<1>::val());
    printf("%d\n",baz<1,2>::val());
    FOO(bar<10>);       // OK
    FOO(baz<20,30>);    // error: too many arguments provided to function-like macro invocation
    FOO((baz<20,30>));  // error: '::val' has not been declared
}
#包括
#定义FOO(v)printf(“%d\n”,v::val())
模板
结构条{
静态int val(){return N;}
};
模板
结构baz{
静态int val(){返回N+M;}
};
int main(){
printf(“%d\n”,bar::val());
printf(“%d\n”,baz::val());
FOO(bar);//好的
FOO(baz);//错误:为宏调用之类的函数提供的参数太多
FOO((baz));//错误:'::val'尚未声明
}
使用clang++和g++

它应该被视为一个bug吗?

不,它不是bug

c预处理器与语言的其他部分不同,它按照自己的规则运行。改变这一点将极大地破坏兼容性,CPP是高度严格标准化的

解决这些逗号问题的通常方法是

typedef baz<20,30> baz2030_type;
FOO(baz2030_type);
typedef-baz-baz\u型;
FOO(巴扎型);

宏的参数被视为纯文本字符串,参数之间用逗号分隔。因此,模板中的逗号将被视为分隔符。因此,预处理器会认为您已将两个参数传递给一个参数宏,因此会出现错误

C/C++预处理器将逗号识别为宏参数分隔符,除非它们嵌套在括号内。只有括号。括号、大括号和模板标记不计算在内:

列表中的各个参数由逗号预处理标记分隔,但匹配的内括号之间的逗号预处理标记不会分隔参数。(C++14§16.3/11;C11§6.10.3/11)

(上面提到的一个副作用是,您可以使用不平衡的大括号和方括号作为宏参数。这通常不是一个好主意,但如果必须的话,您可以这样做。)

因此,偶尔会出现问题;当参数被认为是一个代码块时,常见的参数是不需要的多个参数:

MY_FANCY_MACRO(1000, { int i=0, j=42; ... })
在这里,调用宏时使用(至少)3个参数,尽管编写宏时可能接受2

使用现代C++(和C)编译器,您有一些选择。以相当主观的顺序:

  • 将宏重写为内联函数。如果参数是代码块,考虑使用模板函数,它可以接受lambda或其他函子。如果参数是类型,则将其改为模板参数

  • 如果用多余的括号括住参数在语法上是有效的,那么就这样做。但在这种情况下,几乎可以肯定上述建议(1)会起作用

  • 定义:

    #define COMMA ,
    
    并在必要时使用:

     FOO(baz<20 COMMA 30>);
    

  • 你可以设计宏来提取括号内的参数,但是这个例子当然不需要宏。一个相关的问题是:C++预处理器知道C++吗?C++预处理器没有什么变化,因为它只是C预处理器……克里斯,谢谢,用你的消息的措辞我找到了一个类似的问题的答案,这是一个很好的链接,感谢它的预处理器对C++语法一无所知,它是一个非常愚蠢的宏处理器遵循非常简单的规则。
    #define FOO(...) printf("%d\n",__VA_ARGS__::val())