Search code examples
c++variadic-functionsellipsis

Why doesn't C++ support strongly typed ellipsis?


Can someone please explain to me why C++, at least to my knowledge, doesn't implement a strongly typed ellipsis function, something to the effect of:

void foo(double ...) {
 // Do Something
}

Meaning that, in plain speak: 'The user can pass a variable number of terms to the foo function, however, all of the terms must be doubles'


Solution

  • Historically, the ellipsis syntax ... comes from C.

    This complicated beast was used to power printf-like functions and is to be used with va_list, va_start etc...

    As you noted, it is not typesafe; but then C is far from being typesafe, what with its implicit conversions from and to void* for any pointer types, its implicit truncation of integrals/floating point values, etc...

    Because C++ was to be as close as possible as a superset of C, it inherited the ellipsis from C.


    Since its inception, C++ practices evolved, and there has been a strong push toward stronger typing.

    In C++11, this culminated in:

    • initializer lists, a short-hand syntax for a variable number of values of a given type: foo({1, 2, 3, 4, 5})
    • variadic templates, which are a beast of their own and allow writing a type-safe printf for example

    Variadic templates actually reuse the ellipsis ... in their syntax, to denote packs of types or values and as an unpack operator:

    void print(std::ostream&) {}
    
    template <typename T, typename... Args>
    void print(std::ostream& out, T const& t, Args const&... args) {
        print(out << t, args...); // recursive, unless there are no args left
                                  // (in that case, it calls the first overload
                                  // instead of recursing.)
    }
    

    Note the 3 different uses of ...:

    • typename... to declare a variadic type
    • Args const&... to declare a pack of arguments
    • args... to unpack the pack in an expression