Cada instancia de esa rareza se empareja con un caso de una sola elipsis regular.
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; };
Supongo que la elipsis doble tiene un significado similar a _ArgTypes..., ...
, es decir, una expansión de plantilla variada seguida de una lista de varargs de estilo C.
Aquí hay una prueba que respalda esa teoría ... Creo que tenemos un nuevo ganador para el peor pseudo operador de la historia.
Editar: Esto parece ser conforme. §8.3.5 / 3 describe una forma de formar la lista de parámetros como
lista de declaraciones de parámetros opt ... opt
Entonces, la elipsis doble está formada por una lista de declaración de parámetros que termina con un paquete de parámetros, seguida de otra elipsis.
La coma es puramente opcional; §8.3.5 / 4 dice
Donde sintácticamente correcto y donde "..." no es parte de un declarador abstracto, ", ..." es sinónimo de "...".
Esto está dentro de un declarador abstracto, [editar] pero Johannes hace un buen punto de que se refieren a un declarador abstracto dentro de una declaración de parámetro. Me pregunto por qué no dijeron "parte de una declaración de parámetro" y por qué esa oración no es solo una nota informativa ...
Además, va_begin()
in <cstdarg>
requiere un parámetro antes de la lista de varargs, por lo que el prototipo f(...)
específicamente permitido por C ++ es inútil. Hacer referencias cruzadas con C99, es ilegal en simple C. Entonces, esto es de lo más extraño.
Nota de uso
A pedido, aquí hay una demostración de la doble elipsis:
#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 );
}
...
sigue...
.