2016-09-23 4 views
3

я заметил, что оба GCC и MSVC довольны следующий код:функция VARIADIC без имени аргумента

#include <iostream> 
void foo(...); 

int main() 
{ 
    foo(); 
} 

void foo(...) 
{ 
    std::cout << "foo\n"; 
} 

Более конкретно, код был запущен под GCC 6.2.0 и Visual Studio 2015.

Я знаю, что C требует, по крайней мере, один имя параметра предшествующего многоточие, который позволяет обрабатывать любое количество аргументов с использованием специализированных va_start, va_args и va_end макросов из <stdarg.h> (здесь <cstdarg>) заголовка. В противном случае он даже не будет компилироваться.

Есть ли у C++ специальная обработка для формы «чистого эллипса» или она не подходит для извлечения аргументов, то есть разрешена, но совершенно непрактична?

+0

Когда вы говорите о компиляторах, укажите также * версии *. – Nawaz

+0

@Nawaz: Спасибо за улучшение вопроса. –

+0

Довольно четко сформулированный вопрос, но -1, потому что это ясно сказано в документации cppreference для вариативных аргументов, и мне непонятно, почему вы просто не прочитали его. Должно быть, это был самый первый этап в ваших исследованиях. –

ответ

3

C++ Variadiac arguments are explained here. Этот синтаксис поддерживается в C++, но аргументы не доступны:

В языке программирования С, по крайней мере один именованный параметр должен появиться перед параметром многоточие, так printz(...); не является действительным.

В C++, эта форма допускается, даже если аргументы, переданные таким функции не доступны, и обычно используется в качестве запасного варианта перегрузки в SFINAE, используя самый низкий приоритет многоточие преобразования в разрешении перегрузки. Этот синтаксис для вариативных аргументов был введен в 1987 C++ без запятой перед многоточием. Когда C89 принял прототипы функций из C++, он заменил синтаксис , которому требуется запятая. Для совместимости, C++ 98 принимает как C++ - стиль f(int n...) и C-стиль f(int n, ...)

+0

Вы были немного быстрее меня, я собирался вставить точно то же самое :) –

2

В C++ это разрешено, потому что даже если нет имени параметра прежде, ... только будет недоступной VARIADIC аргумент.

В C нет перегрузок, и функция, которая получает только ..., может стать отличным источником ошибок во время выполнения. Недопустимые varargs не полезны C.

В C++ он в настоящее время используется как функция раковины для sfinae. Компиляторы всегда будут выбирать другую перегрузку, если это возможно, прежде чем разрешать вызов функции с переменным параметром. Это справедливо для цели sfinae:

template<typename F, typename... Ts> 
struct is_callable { 
private: 

    template<typename T, typename... Args> 
    static decltype(
     static_cast<void>(std::declval<T>()(std::declval<Args>()...)), 
     std::true_type{} 
    ) test(int); 

    template<typename...> 
    static std::false_type test(...); // not a template variadic, classic vararg here. 

public: 
    // Here, the compiler will try the first version of the function 
    // Because '...' is not the preferred overload 
    // If the return type expression don't yield to a type, the compiler 
    // will have no choice but to pick the variadic one, 
    // resulting in a std::false_type 
    using type = decltype(test<F, Ts...>(0)); 
}; 
+0

Не уверен, что пример '(int, double)' имеет значение? –

+0

Ну, это показывает, что C++ в порядке с неназванным параметром, а varargs не отличаются –

+0

Они значительно отличаются. Почти нет отношения между нормальным параметром (будь то именованным или иным) и списком varargs. –

Смежные вопросы