在C ++中,我可以定义一个具有可变数量参数的函数,如下所示:
void a(int a...) {
std::cout << a << std::endl;
}
并称之为:
a(100, 200, 300);
但是,显然我只能访问第一个参数:调用的输出是100
。
如何使用此表示法访问其他参数?
答案 0 :(得分:4)
你的语法是......不幸的,并且是指C风格的vararg函数。
在C ++ 11中,你应该更喜欢variardic template
。最简单的方法是这样的:
首先,一些帮助代码:
#include <utility>
template<typename Lambda>
void for_each_arg( Lambda&& unused ) {}
template<typename Lambda, typename Arg1, typename... Args>
void for_each_arg( Lambda&& closure, Arg1&& arg1, Args&&... args ) {
closure( std::forward<Arg1>(arg1) );
for_each_arg( std::forward<Lambda>(closure), std::forward<Args>(args)... );
}
现在,我们使用它:
#include <iostream>
template<typename... Args>
void foo( Args&&... args ) {
for_each_arg( [](int x){
std::cout << x << "\n";
}, std::forward<Args>(args)... );
}
int main() {
foo( 1, 2, 3 );
}
我们可以访问每个参数,并确保它们转换为int
。请注意,转换为int
会延迟到for_each_arg
的正文调用。
答案 1 :(得分:1)
如果使用var args接口,则需要能够从命名参数中分辨出总共提供了多少个参数。例如,<stdio.h>
函数通过将格式字符串作为最后一个命名参数,然后使用参数列表中指定的参数来执行此操作。要访问参数,您需要使用各种va_...
函数和类型。
使用可变参数模板会好得多:
template <typename... T>
void f(T... a) {
// just expand the parameter pack over here
}
答案 2 :(得分:0)
另一种可变解决方案:
template<typename T, typename... Vs>
void print(T&& t, Vs&&... vs) {
std::cout << std::forward<T>(t) << std::endl;
int sink[] { (std::cout << " " << std::forward<Vs>(vs) << std::endl, 0)... };
(void)sink; // silence "unused variable" warning
}
其中包含不需要帮助者的好处。我们使用包扩展将每个参数一次转发给cout。出于语法原因,我利用逗号运算符使表达式(cout..stuff ..,0)解析为整数,然后我们将其丢弃为数组;这让我们可以在复杂语句中使用包扩展运算符。
答案 3 :(得分:0)
强制执行int
类型的解决方案
但使用方法略有不同
#include <initializer_list>
#include <iostream>
// Or you may use std::vector
void print(const std::initializer_list<int>& a) {
for (auto elem : a) {
std::cout << elem << std::endl;
}
}
int main(int argc, char *argv[])
{
print({1, 2, 3}); // extra braces.
return 0;
}
答案 4 :(得分:0)
使用您的函数a
的示例代码:
#include <iostream>
#include <cstdarg>
void a(int a...)
{
va_list args;
va_start(args, a);
int b = va_arg(args, int);
int c = va_arg(args, int);
std::cout << a << ", " << b << ", " << c << std::endl;
}
int main()
{
a(100, 200, 300);
return 0;
}
变量参数语法不知道参数的数量或类型。因此,参数列表中的某些内容必须指明参数的数量和可能的类型。有几种方法通常用于确定参数的数量:
在这个例子中,我简单地假设有三个参数。使用更多或更少的参数调用a
将导致未定义的行为(读取,随机结果,崩溃)。