我们如何更改此函数以支持多个参数

How do we change this function to support multiple arguments?

本文关键字:支持 参数 函数 何更改 我们      更新时间:2023-10-16
#include <iostream>    
using namespace std;
class SampleClass
{
  public:      
    int test(int ... arguments)
    {
        cout << arguments[0] << endl; // Access first element in array
        return sizeof(arguments);
    }
};
int main()
{   
   SampleClass lol;       
   cout << lol.test(3, 1, 4, 2, 5, 0) << endl;       
   return 0;
}

由于我对C++语义的理解有限,test函数失败。但是我该如何修复它,以便它可以访问参数 lits 中的第一个元素,然后返回 arguments 的大小?


正如@Nik指出的那样,我显然可以在数组中传递,但这并没有真正的乐趣!我尝试这样做只是为了学习 - 看看这在C++中是否可行。

既然我们都在猜测你想要什么,我就抛出:

template <typename ... Ts>
size_t test(Ts ... arguments) {
    auto unused = { 0, ((cout << '[' << arguments << "]n"), 0)...};
    (void)unused;
    return sizeof...(arguments);
}

它适用于不同类型的参数(住在科利鲁(。不过,这个解决方案有点太"聪明"了,无法阅读。

这里的诀窍是构建一个大括号初始化列表 - {...}的东西 - 其元素通过按顺序处理可变参数来初始化。然后,您说服编译器所述初始值设定项列表不用于任何内容,因此代码将进行优化以仅生成所需的副作用。

C++ 中的逗号运算符计算最右侧子表达式的值。计算其他子表达式并丢弃其值。因此,((cout << '[' << arguments << "]n"), 0)具有将一些东西转储到cout(包括可变参数之一(并计算为 0 的效果。使用...扩展包后,该行代码实际上是:

auto unused = { 0, ((cout << '[' << arg0 << "]n"), 0),
                   ((cout << '[' << arg1 << "]n"), 0),
                   ((cout << '[' << arg2 << "]n"), 0) };

cout垃圾被评估其副作用并丢弃,整个东西被推断为std::initializer_list<int>就像我们写的那样

auto unused = { 0, 0, 0, 0 };

(开头有额外的零,以避免有人在没有参数的情况下调用函数时出现语法错误。

(void)unused;线正在铸造unused void。它将编译为绝对没有,但通常也会告诉编译器不要警告我们unused是一个未使用的变量。

尝试这样的事情

double test( int num, ... )
{
  va_list arguments;                     // A place to store the list of arguments
  double sum = 0;
  va_start ( arguments, num );           // Initializing arguments to store all values after num
  for ( int x = 0; x < num; x++ )        // Loop until all numbers are added
    sum += va_arg ( arguments, double ); // Adds the next value in argument list to sum.
  va_end ( arguments );                  // Cleans up the list
  return sum / num;                      // Returns the average
}

所以你的点在你的参数列表的错误一侧。我希望这有所帮助,祝你好运。

嗯。您正在尝试混合C++的两个功能,variadic-templatesvariable-length argument list。您的代码根本无法编译,因为您在这里没有模板,并且声明应该是variable-length argument list

int test(int arguments...)

您可以使用标头中的函数访问此列表中的值cstdarg

有了variadic-templates你可以做以下事情

class Derived
{
public:
    template<int... arguments>
    int test()
    {
       int array[] = {arguments...};
       return sizeof(array) / sizeof(*array);
    }
};

像这样使用它

cout << lol.test<3, 1, 4, 2, 5, 0>() << endl;

我不太确定我是否完全理解你的问题。如果您想访问函数而不是模板的"第一个"参数,我认为这样的事情会为您完成,但我可能完全误解了您在这里的目的:

#include <iostream>
template<typename... Args>
int foo(int arg0, Args... args);
template<>
int foo(int arg0)
{
    // here just to catch expansion
    std::cout << '[' << arg0 << ']' << std::endl;
    return 1;
}
template<typename... Args>
int foo(int arg0, Args... args)
{
    foo(arg0);
    foo(args...);
    return 1 + sizeof...(args);
}
int main()
{
    std::cout << foo(1,2,3,4,5) << std::endl;
    std::cout << foo(100,200,300) << std::endl;
    int a=10, b=20;
    std::cout << foo(a,b) << std::endl;
    return 0;
}

输出

[1]
[2]
[3]
[4]
[5]
5
[100]
[200]
[300]
3
[10]
[20]
2

您有多种选择。

1(使用椭圆(只有无限的arg列表(:

int foo(int a1, ...);

您的代码需要像 printf 一样解析椭圆。 您将被限制为内置 C 类型。

2( 使用多个模板:

template<typename T1> int foo(T1 a1);
template<typename T1, typename T2> int foo(T1 a1, T2 a2);
// more templates for more arguments
This method us used, usually up to 10 parameters (10 template functions)

3( 使用具有默认值或非法值的函数,这样您就会知道哪个是最后一个有效参数:

 int foo(int a1, int a2 = -1, int a3 = -1, int aN = -1);