Кожен екземпляр цієї дивацтва поєднується із випадком регулярного одиничного еліпсису.
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; };
Я здогадуюсь, що подвійний еліпсис схожий за своїм значенням _ArgTypes..., ...
, тобто варіативне розширення шаблону з подальшим списком вараг у стилі С.
Ось тест, який підтверджує цю теорію ... Я думаю, що у нас є новий переможець для найгіршого псевдооператора коли-небудь.
Редагувати: це, здається, відповідає. § 8.3.5 / 3 описує один із способів формування списку параметрів як
параметр-декларація-список opt ... opt
Таким чином, подвійний еліпсис формується списком-декларацією параметрів, що закінчується пакетом параметрів, а потім - іншим еліпсісом.
Кома є суто необов’язковою; § 8.3.5 / 4 говорить
Там, де синтаксично правильно і де "..." не входить до конспекту-декларатора, ", ..." є синонімом "...".
Це знаходиться в абстрактному-опису, [ред] , але Johannes робить хорошу точку , що вони мають в виду абстрактну-опису в параметрі-декларації. Цікаво, чому вони не сказали "частина декларації параметра", і чому це речення не є просто інформаційною запискою ...
Крім того, va_begin()
в <cstdarg>
вимагає параметра перед змінною довжиною списку, тому прототип f(...)
спеціально дозволено C ++ марно. Перехресне посилання на C99 є незаконнім у звичайній C. Отже, це найбільш химерно.
Примітка про використання
За запитом, ось демонстрація подвійного еліпсису:
#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 );
}
...
слідує...
.