Каждый случай этой странности сопряжен со случаем обычного единственного многоточия.
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..., ...
похоже на расширение шаблона с переменным числом аргументов, за которым следует список переменных в стиле C.
Вот тест, подтверждающий эту теорию ... Я думаю, что у нас есть новый победитель наихудшего псевдооператора в истории.
Изменить: похоже, это соответствует. §8.3.5 / 3 описывает один способ сформировать список параметров как
список-объявлений-параметров opt ... opt
Таким образом, двойное многоточие формируется списком-объявлением параметров, заканчивающимся пакетом параметров, за которым следует еще одно многоточие.
Запятая не обязательна; §8.3.5 / 4 говорит
Если синтаксически правильно и где «...» не является частью абстрактного декларатора, «, ...» является синонимом «...».
Это находится в абстрактном-описателя, [править] , но Johannes делает хорошую точку , что они имеют в виду абстрактную-описателя в параметре-декларации. Интересно, почему они не сказали «часть объявления параметра» и почему это предложение не просто информативное примечание…
Кроме того, va_begin()
in <cstdarg>
требует параметра перед списком varargs, поэтому прототип, 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 );
}
...
следует...
.