1

Possible Duplicate:
Variable number of arguments in C++?

May I not set the number of arguments of a function with variable number of arguments? As an example: can the following interface be implemented?

int sum(...) { ... }

sum(1, 2, 3, 4); // return 10
Community
  • 1
  • 1
Marshall
  • 87
  • 2
  • 8
  • 6
    http://en.wikipedia.org/wiki/Variadic_function – Mysticial Jul 16 '12 at 23:08
  • Shouldn't be hard to set up a variadic template to do this, assuming your compiler supports them. I'd post an answer, but I don't have such a compiler handy to test my code. –  Jul 17 '12 at 00:09

5 Answers5

3

Conventional variadic functions are messy and not type-safe, but in C++11 you can do this cleanly using variadic templates and (compile-time) recursion:

// Base case for recursion
template <typename T>
inline T sum(T n) {
  return n;
}

// Recursive case
template <typename T, typename... Args>
inline T sum(T n, Args... args) {
  return n + sum(args...);
}

Since it's a template, this'll work for any types that have an operator+ defined:

std::cout << sum(1, 2, 3) << std::endl;  // Prints 6
std::cout << sum(3.14, 2.72) << std::endl;  // Prints 5.86

However, because the return type of the recursive template function is taken from the first argument only, you can get suprising results if you mix different argument types in one call: sum(2.5, 2) returns 4.5 as expected, but sum(2, 2.5) returns 2 because the return type is int, not double. If you want to be fancy, you can use the new alternative function syntax to specify that the return type is whatever the natural type of n + sum(args...) would be:

// Recursive case
template <typename T, typename... Args>
inline auto sum(T n, Args... args) -> decltype(n + sum(args...)) {
  return n + sum(args...);
}

Now sum(2.5, 2) and sum(2, 2.5) both return 4.5.

If your actual logic is more complex than summation, and you don't want it inlined, you can use the inline template functions to put all the values into some sort of container (such as a std::vector or std::array) and pass that into the non-inline function to do the real work at the end.

Wyzard
  • 33,849
  • 3
  • 67
  • 87
  • I'm guessing you're using GCC if you're using variadic templates. The trailing return syntax [works fine on ideone](http://ideone.com/uVS8x) and also GCC 4.7.1 from http://nuwen.net/mingw.html. If you're interested, it's a great distribution. – chris Jul 17 '12 at 00:48
  • @chris, I'm using GCC 4.7.1, and I know the trailing return syntax works in general. But using a return type of `decltype(n + sum(args...))` didn't compile — it complained that it couldn't find a matching template. I tried a few things, but didn't spend a great deal of time on it. – Wyzard Jul 17 '12 at 01:02
  • Ok, I tried that exact code on the end of the recursive `sum` and it worked just fine: `inline auto sum (T n, Args... args) -> decltype (n + sum(args...))` – chris Jul 17 '12 at 01:06
  • Strange, now it works for me too. I must've had a typo somewhere last time. Thanks for the sanity check. – Wyzard Jul 17 '12 at 01:29
1

You probably want to do this by writing the function to take something like a vector<int>, which you'll construct on the fly with a braced initializer list:

int sum(std::vector<int> const &n) { 
    return std::accumulate(begin(n), end(n), 0);
}

If there's some possibility the numbers might be (for example) floating point instead, you probably want to write it as a template instead:

template <class T>
T sum(std::vector<T> const &n) { 
   return std::accumulate(begin(n), end(n), T());
}

Either way, you'd invoke this just marginally differently:

int x = sum({1,2,3,4});

Warning: this feature was added to C++ fairly recently, so some compilers (e.g., VC++) don't support it yet -- though others (e.g., g++ 4.7+), do.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
0

No, you can't.

Just don't use variable arguments. They suck in every conceivable fashion and are completely not worth anybody's time.

Puppy
  • 144,682
  • 38
  • 256
  • 465
0

A C++ variadic function must know how many (and what type) of arguments it was passed. For example, printf's format string tells it what extra arguments to expect.

Your sum has no way of knowing if it got 4 ints or 10. You could make the 1st argument a length:

int sum(int howmany, ...) { ... }

so the function knows how many ints follow. But really you should just pass an array (or vector if you're feeling C++'y)

Adam
  • 16,808
  • 7
  • 52
  • 98
  • If you're feeling really adventurous you could use wrap the function call in a Boost macro that prepends the number of arguments... – Neil Jul 16 '12 at 23:16
0

There are multiple ways to solve your issue. I'll go over a few:

Method 1: -Create a series of overloaded sum functions to suit your needs.

Cons -code bloat

This can be implemented by making multiple functions with headers:

int sum(int a);
int sum(int a, int b);
int sum(int a, int b, int c);

etc...

Method 2: -create a custom class with a linked list, and pass in a pointer to the head of the linked list. This is probably your best move in this case, assuming you don't know the amount of data to be passed in.

Function header:

int sum(LinkedList *headPointer);

Method 3: -pass in an array of variables

Function header:

int sum(int input[]);

Method 4: -create a function with auto-set variables

Function header:

int sum(int a=0, int b=0, int c=0, int d=0,... int n=0);
BenMorel
  • 34,448
  • 50
  • 182
  • 322
kabirpong
  • 40
  • 5
  • another one: int sum(int a=0, int b=0, int c=0, int d=0, int e=0) {...} – marcinj Jul 16 '12 at 23:16
  • Why a custom list class and not a container from the STL? – betabandido Jul 16 '12 at 23:16
  • good call luskan, this is another method that will auto-set the variables you don't pass in to 0. could work depending on what your funciton does. – kabirpong Jul 16 '12 at 23:16
  • @betabandido Either way will work, i use custom list classes for the learning experience it offers. acts as a good refresher – kabirpong Jul 16 '12 at 23:18
  • 1
    @kabirpong Indeed it might be a good idea if you want to refresh how lists are made, but probably not the best idea when giving advice to someone else :) – betabandido Jul 16 '12 at 23:19