Jede Instanz dieser Kuriosität ist mit einem Fall einer regulären einzelnen Ellipse gepaart.
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; };
Ich vermute, dass die doppelte Ellipse eine ähnliche Bedeutung hat wie _ArgTypes..., ...
eine variable Vorlagenerweiterung, gefolgt von einer Varargs-Liste im C-Stil.
Hier ist ein Test , der diese Theorie unterstützt… Ich denke, wir haben einen neuen Gewinner für den schlechtesten Pseudooperator aller Zeiten.
Bearbeiten: Dies scheint konform zu sein. §8.3.5 / 3 beschreibt eine Möglichkeit, die Parameterliste zu bilden als
Parameterdeklarationsliste opt ... opt
Die Doppelellipse wird also durch eine Parameterdeklarationsliste gebildet, die mit einem Parameterpaket endet, gefolgt von einer weiteren Ellipse.
Das Komma ist rein optional; §8.3.5 / 4 sagt
Wo syntaktisch korrekt und wo "..." nicht Teil eines Abstract-Deklarators ist, ist ", ..." gleichbedeutend mit "...".
Dies ist innerhalb eines abstrakten Deklarators, [Bearbeiten], aber Johannes macht einen guten Punkt, dass sie sich auf einen abstrakten Deklarator innerhalb einer Parameterdeklaration beziehen. Ich frage mich, warum sie nicht "Teil einer Parameterdeklaration" gesagt haben und warum dieser Satz nicht nur eine informative Notiz ist ...
Weiterhin va_begin()
in <cstdarg>
erfordert einen Parameter , bevor die Liste varargs, so dass der Prototyp f(...)
speziell von C ++ erlaubt ist nutzlos. Querverweise mit C99 sind in der Ebene C illegal. Das ist also höchst bizarr.
Verwendungshinweis
Auf Anfrage finden Sie hier eine Demonstration der doppelten 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 );
}
...
folgt...
.