“……” 这种 C++ 语法已被标准弃用
去年,我在“What does the …… mean in C++?”一文中专门介绍过 ......
这种极其罕见的 C++ 语法,它其实是 ..., ...
的省略语法。以下这三种写法完全等价:
template<class... Args> void f(Args......) {}
template<class... Args> void f(Args... ...) {}
template<class... Args> void f(Args..., ...) {}
第一个 ...
用于扩展 C++ 可变模板参数包,而第二个 ...
用于匹配 C 语言中 Variadic functions 的旧式变参。
完整的用法及实例在原文中已经详细讲述,没有读过的可以移步阅读。
到了 C++26,前两种写法被弃用,逗号不再可以省略。原因主要有两点:一是会对未来任何试图使用 int...
这种语法的提案产生影响;二是许多用户把 int...
理解为一个模板参数包,而非 Ellipsis Parameters(省略符参数),容易造成困惑和误用。
弃用后,语法规则变为:
parameter-declaration-clause:
parameter-declaration-listopt …opt
…
parameter-declaration-listopt
parameter-declaration-list , …
于是,以 int...
(泛指)作为 int, ...
等价用法的行为全部变得非法。例如:
void f(int...); // deprecated
void f(int x...); // deprecated
void g(auto...); // OK, declares a function parameter pack
void h(auto......); // deprecated
template<class... Ts> void a(Ts...); // OK, function template parameter pack
还有下面这两个语法相近却意义不同的例子:
// abbreviated variadic function template
void g(auto ...args);
// abbreviated non-variadic function template with ellipsis parameter
void g(auto args...);
第二个用法如今已被弃用。
顺便提一下,之前 T...
既可以被解释为模板参数包,也可以被解释为 T
紧跟着一个 Ellipsis Parameter。之所以未曾出现歧义,是因为编译器会优先将其解释为模板参数包。如今只剩下第一种解释,完全不会出现歧义。
说明符 ...
依旧是合法的,与 C 中的行为保持兼容。简言之,下面这两种写法仍然表示 Ellipsis Parameters:
// OK, ellipsis parameters, compatible with C
void f(...);
void g(int, ...);