具有可变数量参数但没有任何显式参数的函数
Function with a variable number of parameters without any explicit parameters
如何在C++中使用以下形式的函数:void function(...) {}
?
确实需要至少一个隐式参数吗?
从注释重复:
C99和C++11之间似乎有一个有趣的区别:C++11允许函数声明void foo(...)
,因为参数声明子句中的函数声明列表是可选的:[dcl.fct]
功能声明:
D1 (
参数声明子句)
cv限定符seqoptref限定符opt异常规范option属性说明符seqopt
参数:
参数声明子句:
参数声明列表opt...
opt
参数声明列表, ...
(请注意参数声明列表和...
在此处分别为opt,这意味着您可以省略其中一个或另一个或两者。clang++和g++支持此解释。)
在C99中,不允许此声明,因为参数列表在的参数类型列表:6.7.5/1 中不是可选的
功能声明:
直接声明符
(
参数类型列表)
参数:
参数类型列表:
参数列表
参数列表, ...
由于va_start
等宏/函数是从C99继承的,因此在C++中,无法使用与省略号匹配的参数和空的参数声明列表。
C99:7.15.1.4 中va_start
的描述
void va_start(va_list ap,
parmN);
[…]
参数parmN是变量中最右边参数的标识符函数定义中的参数列表(, ...
之前的那个)。[…]
强调我的。C99假设省略号之前有一个参数,因为在C99中声明一个带有省略号但没有参数的函数是不合法的。
然而,我可以看到使用带省略号但在C++中没有任何参数的函数的两个原因:
-
过载解决方案。将参数与省略号匹配会导致重载的排名非常低:省略号转换序列比任何用户定义的标准转换序列都差[over.ics.rank]/2。这对元编程很有用:
char foo(int); int foo(...); struct S{}; S s; sizeof(foo(42)); // yields 1 sizeof(foo(s)); // yields sizeof(int)
-
实现定义的技巧。您的实现可能提供了访问那些与省略号匹配的参数的方法。例如,参见BobTFish的示例
如果您想保持某种平台独立性,您至少需要一个参数并使用va_arg宏。
如果您知道体系结构和调用约定的低级别细节,那么您可以直接从寄存器和/或堆栈中提取参数(取决于各种参数的最终位置)。
鉴于va_start
"函数"需要一个参数来设置va_list
,我认为不可能以可靠且可移植的方式来实现这一点。很可能找到在特定平台上有效的东西,但如果您更改编译器,为不同的平台编译,在某些情况下,即使您使用不同的编译器选项进行编译(或更改函数中的代码,例如引入局部变量),也不要指望它能起作用。
...
va_list vl;
va_start(vl, arg);
...
当然,你的另一个问题是知道什么时候没有争论(这将是一个有效的案例)。所以,如果你至少没有一个论点,那么当你根本没有通过任何论点时会发生什么?你是怎么"知道"这种情况的?
- 用于检查值是否为其任何参数的帮助程序函数
- C++ - 声明指向返回任何类型并获取任意数量参数的函数的指针
- C++部分概念 id:显式模板规范顺序/第一个参数的特殊状态的原因是什么?
- VkSurfaceKHR 指针的值在函数调用后更改,无需任何显式赋值
- 显式指定的模板参数包
- 实例化模板时,我是否必须显式显示参数包中的类型?
- 为什么覆盖虚函数时需要显式模板参数?
- 如何制作可以接受任何类型的参数的 std::函数和 lambda
- 使用显式模板参数列表和 [temp.arg.explicit]/3 的函数调用的演绎失败
- MSVC 错误:4 个重载中的任何一个都无法转换所有参数类型
- 在未显式传递参数时默认使用 lambda 的用户输入
- 有没有办法在 c++ 中显式调用可选参数?
- 在 OpenMP 中使用并行块时没有看到任何显着改进C++
- 模板模板参数的显式匹配
- 模板参数的显式指定参数无效,该参数是 constexpr
- C 11中函数参数的显式模板函数参数规范和隐式转换
- 在可变参数模板类中使用可变参数进行显式专用化 [MSVS '12:12 年 11 月 CTP:错误 C3522]
- 不能从同一类的另一个构造函数调用具有所有默认参数的显式构造函数
- 具有可变数量参数但没有任何显式参数的函数
- 使用参数列表显式实例化类模板