Home > OS >  Sum function in C with unknown number of arguments and types
Sum function in C with unknown number of arguments and types

Time:12-12

The first part of question is create a function (Sum) with unknown number of arguments, i've done it . It works very nice. But i have the struggle in second part , argument with different type like: int, float, double ... in one function call . Any ideals i can fix my program ???

Thanks for your attention.

I think a lot people dont understand my question. I want my program work also with different type od argument . For example: sum(3, int x, int y, double z) or 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 .

but

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

or even all numbers are integer, it's still not work as i expected , it 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;
}

CodePudding user response:

The problem is you assume double as arguments, see this line:

double el = va_arg( arguments, double );

the usual solution is to provide format of the arguments passed to function, like in printf - but I suppose you don't want to do it.

I can suggest you use variadic templates like in this example:

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;
}

You may change return type from T to double.

CodePudding user response:

As a continuation of marcinj's answer, a variadic template is definitely the easiest way to go here. However, like you mentioned, you want to make sure the function be as generic as possible, so I would do it like this:

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

Here sum(Args ... args) means it will take any amount of parameter, include 0 arguments.

Then you can set the return type with trailing return type. You might attempt to do it with:

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

However, this would give a compiler error if you passed 0 arguments to sum(), which is why I added int to it.

Then I used a fold expression to unpack the parameter pack, so (0 ... args) would be equivalent to:

0   arg1   arg2   ...   argN

Note: the trailing return type is not necessary, you could as well just do:

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

It just looks cleaner to me.

CodePudding user response:

In C you can use something called a template function, which allows for different types of variables. You can look at this here: C Function Template

Here is an example:

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

I would recommend passing an std::vector<> into the function and then using a for loop with vector_name.size() to iterate through each element and add them.

  • Related