What Is the Meaning of "... ..." Token? I.E. Double Ellipsis Operator on Parameter Pack

What is the meaning of ... ... token? i.e. double ellipsis operator on parameter pack

Every instance of that oddity is paired with a case of a regular single ellipsis.

  template<typename _Res, typename... _ArgTypes>
struct _Weak_result_type_impl<_Res(_ArgTypes...)>
{ typedef _Res result_type; };

template<typename _Res, typename... _ArgTypes>
struct _Weak_result_type_impl<_Res(_ArgTypes......)>
{ typedef _Res result_type; };

template<typename _Res, typename... _ArgTypes>
struct _Weak_result_type_impl<_Res(_ArgTypes...) const>
{ typedef _Res result_type; };

template<typename _Res, typename... _ArgTypes>
struct _Weak_result_type_impl<_Res(_ArgTypes......) const>
{ typedef _Res result_type; };

My guess is that the double ellipsis is similar in meaning to _ArgTypes..., ..., i.e. a variadic template expansion followed by a C-style varargs list.

Here's a test supporting that theory… I think we have a new winner for worst pseudo-operator ever.

Edit: This does appear to be conformant. §8.3.5/3 describes one way to form the parameter list as

parameter-declaration-listopt ...opt

So the double-ellipsis is formed by a parameter-declaration-list ending with a parameter pack, followed by another ellipsis.

The comma is purely optional; §8.3.5/4 does say

Where syntactically correct and where “...” is not part of an abstract-declarator, “, ...” is synonymous with “...”.

This is within an abstract-declarator, [edit] but Johannes makes a good point that they are referring to an abstract-declarator within a parameter-declaration. I wonder why they didn't say "part of a parameter-declaration," and why that sentence isn't just an informative note…

Furthermore, va_begin() in <cstdarg> requires a parameter before the varargs list, so the prototype f(...) specifically allowed by C++ is useless. Cross-referencing with C99, it is illegal in plain C. So, this is most bizarre.

Usage note

By request, here is a demonstration of the double ellipsis:

#include <cstdio>
#include <string>

template< typename T >
T const &printf_helper( T const &x )
{ return x; }

char const *printf_helper( std::string const &x )
{ return x.c_str(); }

template< typename ... Req, typename ... Given >
int wrap_printf( int (*fn)( Req... ... ), Given ... args ) {
return fn( printf_helper( args ) ... );
}

int main() {
wrap_printf( &std::printf, "Hello %s\n", std::string( "world!" ) );
wrap_printf( &std::fprintf, stderr, std::string( "Error %d" ), 5 );
}

What is the meaning of ... ... token? i.e. double ellipsis operator on parameter pack

Every instance of that oddity is paired with a case of a regular single ellipsis.

  template<typename _Res, typename... _ArgTypes>
struct _Weak_result_type_impl<_Res(_ArgTypes...)>
{ typedef _Res result_type; };

template<typename _Res, typename... _ArgTypes>
struct _Weak_result_type_impl<_Res(_ArgTypes......)>
{ typedef _Res result_type; };

template<typename _Res, typename... _ArgTypes>
struct _Weak_result_type_impl<_Res(_ArgTypes...) const>
{ typedef _Res result_type; };

template<typename _Res, typename... _ArgTypes>
struct _Weak_result_type_impl<_Res(_ArgTypes......) const>
{ typedef _Res result_type; };

My guess is that the double ellipsis is similar in meaning to _ArgTypes..., ..., i.e. a variadic template expansion followed by a C-style varargs list.

Here's a test supporting that theory… I think we have a new winner for worst pseudo-operator ever.

Edit: This does appear to be conformant. §8.3.5/3 describes one way to form the parameter list as

parameter-declaration-listopt ...opt

So the double-ellipsis is formed by a parameter-declaration-list ending with a parameter pack, followed by another ellipsis.

The comma is purely optional; §8.3.5/4 does say

Where syntactically correct and where “...” is not part of an abstract-declarator, “, ...” is synonymous with “...”.

This is within an abstract-declarator, [edit] but Johannes makes a good point that they are referring to an abstract-declarator within a parameter-declaration. I wonder why they didn't say "part of a parameter-declaration," and why that sentence isn't just an informative note…

Furthermore, va_begin() in <cstdarg> requires a parameter before the varargs list, so the prototype f(...) specifically allowed by C++ is useless. Cross-referencing with C99, it is illegal in plain C. So, this is most bizarre.

Usage note

By request, here is a demonstration of the double ellipsis:

#include <cstdio>
#include <string>

template< typename T >
T const &printf_helper( T const &x )
{ return x; }

char const *printf_helper( std::string const &x )
{ return x.c_str(); }

template< typename ... Req, typename ... Given >
int wrap_printf( int (*fn)( Req... ... ), Given ... args ) {
return fn( printf_helper( args ) ... );
}

int main() {
wrap_printf( &std::printf, "Hello %s\n", std::string( "world!" ) );
wrap_printf( &std::fprintf, stderr, std::string( "Error %d" ), 5 );
}

When is an ellipsis needed when dealing with parameter packs?

Ellipses are needed there because sizeof...(Ts) is a special form of sizeof that returns the size of a parameter pack. Ordinary sizeof(Ts) could not be used for this purpose because it needs to remain possible to use standard sizeof behavior in expanded patterns i.e. sizeof(Ts) returns the size of an individual type in an evaluated fold expression.

What are the 6 dots in template parameter packs?

In this case, the two are for different purposes. The first is for parameter pack expansion and the second is for variable argument lists. That particular declaration is to handle functions which take some regular parameters plus a variable argument list.

The difference is between run-time and compile-time variability. A function which takes a variable number of arguments at run-time is special. It is a single function which can handle a variable number of arguments from the caller:

void f(int x,...) // equivalent to void f(int x ...)
{
// Do some run-time logic here to determine what to
// do with parameters after x.
}

This is distinct from the notion that we want to be able to have a template which uses a variety of functions with various parameters which are known at compile time. For example, we could define a function template which takes a pointer to a function and allow the number and types of the arguments to vary:

template <typename... Args>
void g(void (*function_ptr)(Args...))
{
// We can do logic here to call function_ptr with the proper
// number of arguments.
}

Given these functions:

void f1(int);
void f2(int,float);

You can call g with any of them:

g(f1); // fine
g(f2); // also fine

However

g(f); // error

The compiler wouldn't know what to use for the Args parameter pack in g.

Lambda pack capture with ellipsis on both sides - what is the meaning?

It should be ill-formed. Filed 89686 (... and already fixed!) The grammar in [expr.prim.lambda.capture] is:

capture:

    simple-capture ...opt
    ...opt init-capture

You can either have a simple-capture (which would be xs...) or you can have an init-capture (which would be ...xs=xs, an init-capture needs to have an initializer). You cannot have both in one go.

What kind of parameter unpacking is ... ...?

The the last ... is actually equivalent to , ....

Which makes the template parameter:

Res(Args..., ...)

Which means this is a variadic function, with a template variadic number of fixed arguments.

How can I access the types in a C++ template parameter pack?

With abuse of operator overloading and folding expression (C++17), you might do something like that to chain operation:

template <typename ... Fs>
class Chain
{
private:
template <typename F>
struct CallerWrap
{
F f;
CallerWrap(F f) : f(f) {}

template <typename T>
friend decltype(auto) operator+ (const CallerWrap& callerWrap, T&& x)
{
return callerWrap.f(std::forward<T>(x));
}
};

std::tuple<Fs...> tup;
public:

Chain(Fs... fs) : tup{fs... }{}

template <typename T>
decltype(auto) operator()(T x) const {
return std::apply([&x](auto... fs){ return (CallerWrap{fs} + ... + x); }, tup);
}

};

Demo

There are no fold expressions for f1(f2(f3(x))) but there is for f1 + (f2 + (f3 + x)) (and other binary operators).
So we add wrapper to use the later and be equivalent to the former.

What is the meaning of three dots (...) in PHP?

This is literally called the ... operator in PHP, but is known as the splat operator from other languages. From a 2014 LornaJane blog post on the feature:

This feature allows you to capture a variable number of arguments to a function, combined with "normal" arguments passed in if you like. It's easiest to see with an example:

function concatenate($transform, ...$strings) {
$string = '';
foreach($strings as $piece) {
$string .= $piece;
}
return($transform($string)); }

echo concatenate("strtoupper", "I'd ", "like ", 4 + 2, " apples");

(This would print I'D LIKE 6 APPLES)

The parameters list in the function declaration has the ... operator in it, and it basically means " ... and everything else should go into $strings". You can pass 2 or more arguments into this function and the second and subsequent ones will be added to the $strings array, ready to be used.



Related Topics



Leave a reply



Submit