Исторически многоточие синтаксис ...
происходит от С.
Этот сложный зверь был использован для питания printf
-как функций и должен быть использован с va_list
, va_start
и т.д ...
Как вы отметили, он не является типичным; но тогда C далеко не является типичным, что с его неявными преобразованиями от и до void*
для любых типов указателей, его неявное усечение интегралов/значений с плавающей запятой и т. д.
Поскольку C++ должен быть как можно ближе как надмножество C, он унаследовал многоточие от С.
с самого начала практики, C++ эволюционировал, и там был сильный толчок в сторону более сильной типизации.
В C++ 11, это завершилось:
- списков инициализатора, синтаксис стенографии для переменного числа значений данного типа:
foo({1, 2, 3, 4, 5})
- VARIADIC шаблонов, которые животное свой собственные и разрешить запись типа а безопасный
printf
например
шаблонов VARIADIC фактически повторно многоточию ...
в их синтаксисе для обозначения пакетов типов или значений и в качестве распаковки оператора:
void print(std::ostream&) {}
template <typename T, typename... Args>
void print(std::ostream& out, T const& t, Args const&... args) {
print(out << t, args...); // recursive, unless there are no args left
// (in that case, it calls the first overload
// instead of recursing.)
}
Обратите внимание на 3 различных формах использования ...
:
typename...
объявить VARIADIC типа
Args const&...
объявить пакет аргументов
args...
для распаковки упаковки в выражении
Я бы предположил, что вариационные функции были добавлены в C с единственной целью поддержки семейства функций printf, которые должны быть небезопасными по типу. Сама концепция ввода-вывода в формате строки, вероятно, была взята только из предшественников C, таких как BCPL (см. Https://en.wikipedia.org/wiki/BCPL). В современном C++ нет необходимости вводить различные вариабельные функции, так как у нас есть превосходные языковые конструкции, тем более, что C++ 11. К сожалению, у меня нет ссылок на мои догадки. Было бы интересно задать этот вопрос самому Бьярну Страуступу. –
Вы можете сделать 'void foo (double *)' и называть его 'foo ((double []) {1,2,3,4,5})'. Необходимо расширение GNU C++. – user3528438
Неужели это особенность слишком анекдотическая, чтобы ее можно было включить в уже перегруженный язык? Тогда вы должны также утверждать, что 'void foo (double ..., int ..., double ...)' и тому подобное. –