Bu tuhaflığın her örneği, normal tek bir üç nokta vakasıyla eşleştirilir.
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; };
Benim tahminim, çift elips anlam olarak benzerdir _ArgTypes..., ...
, yani bir değişken şablon genişletmesi ve ardından bir C-tarzı vararg listesi.
İşte bu teoriyi destekleyen bir test … Sanırım şimdiye kadarki en kötü sözde operatör için yeni bir kazananımız var.
Düzenleme: Bu uyumlu görünüyor. §8.3.5 / 3, parametre listesini aşağıdaki gibi oluşturmanın bir yolunu açıklar:
parametre bildirim listesi tercih ... tercih
Dolayısıyla, çift üç nokta, bir parametre paketi ile biten bir parametre bildirim listesi ve ardından başka bir üç nokta ile oluşturulur.
Virgül tamamen isteğe bağlıdır; §8.3.5 / 4 diyor ki
Sözdizimsel olarak doğru olduğunda ve "..." bir soyut bildiricinin parçası olmadığında, ", ...", "..." ile eşanlamlıdır.
Bu ise , bir arka-Bildiricisi içinde [değiştir] ama Johannes bir parametre bildiriminin içinde soyut-Bildiricisi atıfta olduğu iyi bir noktasıdır. Neden "parametre bildiriminin parçası" demediklerini ve bu cümlenin neden sadece bilgilendirici bir not olmadığını merak ediyorum ...
Ayrıca, va_begin()
in <cstdarg>
, varargs listesinden önce bir parametre gerektirir, bu nedenle f(...)
C ++ tarafından özel olarak izin verilen prototip işe yaramaz. C99 ile çapraz referans, düz C'de yasadışıdır. Yani, bu çok tuhaf.
Kullanım notu
İstek üzerine, burada çift üç nokta için bir gösterim bulunmaktadır:
#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 );
}
...
ardından gelir...
.