10

I am coding in C++ and have a few questions regarding the ellipsis:

  1. Is it possible to pass in class or class pointer into the ellipsis?

  2. Basically what I want to do is to pass in variable number of arguments in the type of char* and class. I am using ellipsis currently and trying to figure out how to pass in the class. If ellipsis isn't applicable over here, what are the options available?

I want to let the user to directly call the function using func( params 1, params2, ...) without explicitly assigning the params into a vector or array first before passing the vector or array as argument to the function.

Stephane Rolland
  • 38,876
  • 35
  • 121
  • 169
Steveng
  • 5,681
  • 4
  • 17
  • 7

6 Answers6

18

You should consider that using variadic functions (C-style) is a dangerous flaw. If the objects passed to the function mismatch the type awaited, or if you don't put the exact number of parameters awaited, then you basically have a violent crash at runtime.

In Bjarne Stroustrup C++ In Depth Series - C++ Coding Standards - 101 Rules, Guidelines, And Best Practices by Herb Sutter and Andrei Alexandrescu, chapter 98: Don't use varargs (ellipsis)

I deeply subscribe to @tenfour's proposal:

  • use an std::vector that contains all your parameters.
Stephane Rolland
  • 38,876
  • 35
  • 121
  • 169
  • 5
    Others might downvote, but this is clearly the best advice in the thread. It is very unlikely that someone who needs to ask about how to use `...` has given a lot of thought to the design implications of using `...`. – John Dibling Aug 24 '10 at 15:09
  • 8
    Maybe so, but needing to ask about something does not mean that the programmer will remain unqualified to use these features forever. Remember, the programmer who asks whether something is a good idea is a programmer who is thoughtful. – Winfield Trail Sep 08 '13 at 22:04
  • No accepted answer yet. Would appreciate to see a simple use case of the C++ flavor not C. – KcFnMi Oct 06 '22 at 09:43
  • Although the question is tagged C++, we could probably think of a C only oriented solution. I have not yet started to read the book Modern programming in C by E. King, so this is just my guess: I'd say use a C-array. I'll tell you there if I see other advices. – Stephane Rolland Dec 26 '22 at 18:35
10

You can pass whatever you want to variadic functions, but this won't help you in writing convenient functions as you are losing the type information for the arguments.

Depending on what you want to achieve there are better alternatives:

  • chaining operators like << or ():

    helper() << a << b << c;
    helper(a)(b)(c);
    
  • using (pseudo-)variadic templates:

    template<class T0>           void func(T0 t0)        { ... }
    template<class T0, class T1> void func(T0 t0, T1 t1) { ... }
    // ...
    
    // or if you can use C++0x features:
    template<class... Args> void func(Args... args) { ... }
    
  • ... more?
Georg Fritzsche
  • 97,545
  • 26
  • 194
  • 236
  • +1 for the operator overloading. Variadic templates just looks like moving the problem somewhere else rather than solving it. – Skizz Aug 24 '10 at 11:02
  • 1
    The key with variadic templates is that they are type-safe, which is where the danger in C-style variadics lies. – Levi Morrison Aug 24 '15 at 22:53
4

You can pass a class pointer with varargs, yes. But the function receiving the pointer needs to know what to do with it. It will have to cast it to something usable. This is why printf() makes you specify the argument type in the format specifier.

One alternative is to pass a list to the function, like std::vector.

[edit] You might be want to do something to make the syntax shorter, so you can pass in your arguments like:

foo(blah, StartAList(a)(b)(c)(d));

or stream-ish:

foo(blah) >> a >> b >> c >> d;

or by overloading:

void foo(T a) { ... }
void foo(T a, T b) { ... }
void foo(T a, T b, T c) { ... }
tenfour
  • 36,141
  • 15
  • 83
  • 142
  • furthermore, IIRC the standard (at least pre-0x) does not specify if objects are passed by value or by reference. ---- it would probably have to be `foo(T1, T2, T3)`, too. We did that for a `sprintf` replacement, a PITA for sure to generate, but oh boy the sublte bugs it uncoverd! Things that happen once in a million, code paths you never fetch with automated tests, etc. – peterchen Aug 24 '10 at 11:03
3

Using C++0x variadic templates, you can pack all your arguments into a tuple and use the code I posted in the thread below to unpack them into a function call (static function or object function).

How do I expand a tuple into variadic template function's arguments?

Community
  • 1
  • 1
David
  • 3,324
  • 2
  • 27
  • 31
1

True typesafe variable argument functions are possible with the newly introduced feature variable template arguments in C++0x

You can also get by using boost::any

rep_movsd
  • 6,675
  • 4
  • 30
  • 34
  • Okay, but such case it is varidaic template, and the validation is done at compile time. Nothing compare to the utterly dangerous variadic functions. (that's one of the reasons I HATE printf, my personnal opinion) – Stephane Rolland Aug 24 '10 at 10:57
  • That's why you could use a newly defined printf built on the variadic template stuff which is type-safe. http://www2.research.att.com/~bs/C++0xFAQ.html#variadic-templates – David Aug 24 '10 at 11:51
  • I haven't read the article yet, but for the moment I am really pleased with std::stringstream – Stephane Rolland Sep 16 '12 at 08:59
0

If class instance (or pointer) is used always, it is better to use fixed parameter, which is passed before variable parameters list, like format in printf. Regarding ... parameters, they may have any type (including class instance or pointer), and their amount and types depend on some convention between a caller and called function. For example, for printf, such convention is defined by format string. You need to define such "communication protocol", which allows to use variable arguments list. Of course, this is not safe.

Alex F
  • 42,307
  • 41
  • 144
  • 212