Chaque cas de cette bizarrerie est associé à un cas d'ellipse simple normale.
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 pense que la double ellipse a un sens similaire à celui de _ArgTypes..., ...
c'est-à-dire une expansion de modèle variadique suivie d'une liste de varargs de style C.
Voici un test soutenant cette théorie Je pense que nous avons un nouveau gagnant pour le pire pseudo-opérateur de tous les temps.
Editar: Cela semble être conforme. Le §8.3.5/3 décrit une façon de former la liste des paramètres comme suit
liste de déclaration des paramètres opt ... opt
La double ellipse est donc formée par une liste de déclarations de paramètres se terminant par un paquet de paramètres, suivie d'une autre ellipse.
La virgule est purement facultative ; le §8.3.5/4 dit en effet
Lorsque la syntaxe est correcte et que " ... " ne fait pas partie d'un déclarateur abstrait, " , ... " est synonyme de " ... ".
Ce site es au sein d'un déclarateur abstrait, [modifier] mais Johannes a raison de dire qu'ils font référence à un déclarateur abstrait dans une déclaration de paramètres. Je me demande pourquoi ils n'ont pas dit "partie d'une déclaration de paramètres", et pourquoi cette phrase n'est pas simplement une note informative
En outre, va_begin()
en <cstdarg>
nécessite un paramètre avant la liste de varargs, donc le prototype f(...)
spécifiquement autorisé par le C++ est inutile. Si l'on se réfère à C99, c'est illégal en C. C'est donc 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 );
}