Chaque instance de cette bizarrerie est associée au cas d'une seule ellipse régulière.
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; };
Je suppose que la double ellipse a un sens similaire à _ArgTypes..., ...
, c'est- à -dire une expansion de modèle variadique suivie d'une liste de varargs de style C.
Voici un test qui soutient cette théorie… Je pense que nous avons un nouveau gagnant pour le pire pseudo-opérateur de tous les temps.
Edit: Cela semble être conforme. Le §8.3.5 / 3 décrit une manière de former la liste de paramètres comme
liste-déclaration-paramètre opt ... opt
Ainsi, la double ellipse est formée par une liste de déclaration de paramètres se terminant par un pack de paramètres, suivie d'une autre ellipse.
La virgule est purement facultative; §8.3.5 / 4 dit
Là où la syntaxe est correcte et où «...» ne fait pas partie d'un déclarateur abstrait, «, ...» est synonyme de «...».
C'est dans un abstrait déclarateur, [modifier] mais Johannes fait un bon point qu'ils font référence à un résumé-déclarateur dans un paramètre-déclaration. Je me demande pourquoi ils n'ont pas dit "une partie d'une déclaration de paramètre" et pourquoi cette phrase n'est pas qu'une note informative ...
De plus, va_begin()
in <cstdarg>
requiert un paramètre avant la liste varargs, donc le prototype f(...)
spécifiquement autorisé par C ++ est inutile. Les renvois avec C99, c'est illégal en plein C. Donc, c'est très bizarre.
Note d'utilisation
Sur demande, voici une démonstration de la double ellipse:
#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 );
}
...
suivi de...
.