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);
我觉得它看起来更干净。
问题的第一部分是创建一个参数数量未知的函数 (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 更改为双精度。
作为
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);
我觉得它看起来更干净。