C++ 中的 Sum 函数,参数和类型数量未知

Sum function in C++ with unknown number of arguments and types

问题的第一部分是创建一个参数数量未知的函数 (Sum),我已经完成了。它工作得很好。但是我在第二部分遇到了困难,在一个函数调用中使用不同类型的参数,如:int、float、double ...。我可以修复我的程序的任何理想 ???

感谢您的关注。

我想很多人不明白我的问题。 我希望我的程序也可以使用不同类型的 od 参数。 例如: sum(3, int x, int y, double z)sum(4, double x, int y, float z, double t)

cout << func(sum, 5, 1.0, 2.0, 3.0, 4.0, 5.0) << endl; it work nicely with double , as i expected .

但是

cout << func(sum, 5, 1.0, 2.0, 3, 4, 5) << endl; it doesnt work

甚至所有数字都是整数,它仍然没有像我预期的那样工作,它 return 0

cout << func(sum, 5, 1, 2, 3, 4, 5) << endl;

double func(double (*f) (const double*, int) , int num, ...) {


  va_list arguments;

  /* Initializing arguments to store all values after num */
  va_start(arguments, num);
  /* Sum all the inputs; we still rely on the function caller to tell us how
  * many there are */

  auto *array = new double[num];

  for (int x = 0; x < num; x++) {
    double el = va_arg( arguments, double );
    array[x] = el;
  }
  va_end(arguments);                  // Cleans up the list

  return f(array, num);
}

double sum(const double *array, int n) {
  double result = 0;

  for (int i = 0; i < n; ++i) {
      result += array[i];
  }
  return result;
}

在 C++ 中,您可以使用称为模板函数的东西,它允许使用不同类型的变量。您可以在这里查看:C++ Function Template

这是一个例子:

template <typename T>
T add(T num1, T num2) {
   return (num1 + num2);
}

我建议将 std::vector<> 传递给函数,然后使用带有 vector_name.size() 的 for 循环遍历每个元素并添加它们。

问题是你假设 double 作为参数,见这一行:

double el = va_arg( arguments, double );

通常的解决方案是提供传递给函数的参数的格式,就像在 printf 中一样 - 但我想你不想这样做。

我建议您使用可变参数模板,如本例所示:

template<typename T>
T func(T first) {
  return first;
}

template<typename T, typename... Args>
T func(T first, Args... args) {
  return first + func(args...);
}

int main() {
  std::cout << func(5, 1.0, 2.0, 3, 4, 5) << std::endl;
  std::cout << func(5, 1, 2, 3, 4, 5) << std::endl;
  return 0;
}

您可以将 return 类型从 T 更改为双精度。

作为, a variadic template的延续绝对是最简单的方法。然而,就像你提到的,你想确保函数尽可能通用,所以我会这样做:

template<typename ... Args>
auto sum(Args ... args) -> std::common_type_t<int, Args...>
{
    return (0 + ... + args);
}

这里sum(Args ... args)表示它可以接受任意数量的参数,包括0个参数。

然后你可以设置 return 类型与尾随 return 类型。您可以尝试使用:

-> std::common_type_t<Args...>

但是,如果您将 0 个参数传递给 sum(),这将导致编译器错误,这就是我向其添加 int 的原因。

然后我用了一个fold expression来解压参数包,所以(0 + ... + args)就相当于:

((((0 + arg1) + arg2) + ...) + argN)

注意:结尾的 return 类型不是必需的,您也可以这样做:

template<typename ... Args>
std::common_type_t<int, Args...> sum(Args ... args);

我觉得它看起来更干净。