Просматривая текущую реализацию новых заголовков C ++ 11 в gcc, я наткнулся на токен «......». Вы можете проверить, что следующий код компилируется нормально [через ideone.com].
template <typename T>
struct X
{ /* ... */ };
template <typename T, typename ... U>
struct X<T(U......)> // this line is the important one
{ /* ... */ };
Итак, что означает этот токен?
edit: Похоже, ТАК обрезано "......" в заголовке вопроса до "...", я действительно имел в виду "......". :)
c++
c++11
variadic-templates
Vitus
источник
источник
...
следует...
.U...
следует...
. Тем не менее, очень странно.<functional>
и<type_traits>
всегда в контексте списка аргументов функции внутри параметра шаблона.Ответы:
Каждый случай этой странности сопряжен со случаем обычного единственного многоточия.
Я предполагаю, что двойное многоточие по своему значению
_ArgTypes..., ...
похоже на расширение шаблона с переменным числом аргументов, за которым следует список переменных в стиле C.Вот тест, подтверждающий эту теорию ... Я думаю, что у нас есть новый победитель наихудшего псевдооператора в истории.
Изменить: похоже, это соответствует. §8.3.5 / 3 описывает один способ сформировать список параметров как
Таким образом, двойное многоточие формируется списком-объявлением параметров, заканчивающимся пакетом параметров, за которым следует еще одно многоточие.
Запятая не обязательна; §8.3.5 / 4 говорит
Это находится в абстрактном-описателя, [править] , но Johannes делает хорошую точку , что они имеют в виду абстрактную-описателя в параметре-декларации. Интересно, почему они не сказали «часть объявления параметра» и почему это предложение не просто информативное примечание…
Кроме того,
va_begin()
in<cstdarg>
требует параметра перед списком varargs, поэтому прототип,f(...)
специально разрешенный C ++, бесполезен. Перекрестные ссылки с C99 недопустимы в простом C. Итак, это очень странно.Примечание об использовании
По желанию, вот демонстрация двойного многоточия:
источник
std::is_function
«svalue
должно быть истинным , даже если функция С одной переменной длины и потому , что T (U ...) это не соответствует такой функции, вам нужно это безумие. Например, int f (int, char, ...) точно соответствует T (U ......) с T = int, U = {int, char} и токеном "..." varargs.void (int...)
здесь,...
не является частью абстрактного декларатораint
, следовательно, он является синонимомvoid(int, ...)
. Если бы вы написалиvoid(T...)
иT
является пакетом параметров шаблона,...
он будет частью абстрактного декларатора и, следовательно, не будет эквивалентенvoid(T, ...)
.f(...)
широко используется как перегрузка резервной функции в метапрограммировании шаблонов, где эта информация не нужна (и где функция даже не вызывается).на vs2015 разделение запятой необходимо в версии шаблона:
пример создания:
С уважением, FM.
источник