Ogni istanza di quella stranezza è abbinata a un caso di puntini di sospensione singoli regolari.
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; };
La mia ipotesi è che la doppia ellissi abbia un significato simile a _ArgTypes..., ...
, cioè un'espansione del modello variadica seguita da un elenco di variabili in stile C.
Ecco un test a sostegno di questa teoria ... Penso che abbiamo un nuovo vincitore per il peggior pseudo-operatore di sempre.
Modifica: questo sembra essere conforme. §8.3.5 / 3 descrive un modo per formare l'elenco dei parametri come
lista-dichiarazione-parametri opt ... opz
Quindi la doppia ellissi è formata da una lista di dichiarazione di parametri che termina con un pacchetto di parametri, seguita da un'altra ellissi.
La virgola è puramente facoltativa; §8.3.5 / 4 dice
Dove sintatticamente corretto e dove "..." non fa parte di un dichiaratore astratto, ", ..." è sinonimo di "...".
Questo è all'interno di un dichiaratore astratto, [modifica] ma Johannes sottolinea bene che si riferiscono a un dichiaratore astratto all'interno di una dichiarazione di parametri. Mi chiedo perché non abbiano detto "parte di una dichiarazione di parametri" e perché quella frase non sia solo una nota informativa ...
Inoltre, va_begin()
in <cstdarg>
richiede un parametro prima dell'elenco varargs, quindi il prototipo f(...)
specificamente consentito da C ++ è inutile. Riferimento incrociato con C99, è illegale in pianura C. Quindi, questo è molto bizzarro.
Nota di utilizzo
A richiesta, ecco una dimostrazione della doppia ellissi:
#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 );
}
...
seguito da...
.