Можно ли использовать аргументы по умолчанию и переменное количество аргументов в одной функции? - PullRequest
10 голосов
/ 30 апреля 2011

Например, что-то вроде этого:

#include <cstdarg>

void my_function(int it=42, ...)
{
     /* va_list/start/arg/end code here */
}

Что именно означает приведенный выше код на C ++? Он прекрасно компилируется в G ++. Обратите внимание, я не могу представить ни одного сценария, где это было бы полезно или даже то, что он должен делать. Мне просто любопытно.

Ответы [ 3 ]

6 голосов
/ 30 апреля 2011
void my_function(int it=42, ...)

Вы сказали, что эта функция прекрасно компилируется с GCC, но вы не можете использовать аргумент по умолчанию, вам также придется передать аргумент для так называемого параметра по умолчанию, чтобы работать с этой функцией.

my_function("string", 98, 78, 99); //error
my_function(898, "string", 98, 78, 99); //ok, but the param 'it' becomes 898

Задайте себе вопрос:

Первый аргумент 898 соответствует параметру it или соответствует параметру переменной (и вы собираетесь использовать значение по умолчанию 42 для it)?

Компилятор не может знать ваше намерение!

Кстати, Йоханнес указал на хороший момент: вы можете просто позвонить my_function(), не передавая никаких аргументов. Это единственный случай, когда я могу использовать аргумент по умолчанию.


Теперь, если вы измените положение параметра по умолчанию, примерно так:

void f(..., int p = 10); //illegal

Тогда для C ++ это недопустимо.

Опять спросите себя: если бы это было разрешено, то вы могли бы назвать это как:

f(9879, 97897, 7897);

Последний аргумент 7897 соответствует параметру p или соответствует параметру variadic (и вы собираетесь использовать значение по умолчанию 10 для p)?

Компилятор также не может знать ваше намерение в этом случае.

5 голосов
/ 30 апреля 2011

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

Вы можете прекратить предоставлять аргументы в первом аргументе, который имеет аргумент по умолчанию. Если вы позволите аргументам по умолчанию вступить во владение, тогда список переменных аргументов, конечно, будет пустым.

Вы можете предоставить аргументы за пределами именованных параметров, чтобы заполнить список переменных аргументов, и в этом случае ни один из аргументов по умолчанию не будет использоваться.

Как вы указываете, есть ли практическая ситуация, когда это было бы действительно полезно, это другой вопрос.

0 голосов
/ 01 мая 2011
void my_function(int it=42, ...){ /* va_list/start/arg/end code here */}

Ну, этот код должен делать именно так, как он выглядит.Переданный первый параметр (если есть) - это параметр it, а остальное - ....Поэтому, если вы не передадите никаких параметров, тогда вашему параметру it будет присвоено значение по умолчанию (42), а it (что равно 42) - единственный параметр, переданный в функцию.

Код, подобный этому, может быть полезенточно так же, как любое другое использование ... -определенного списка аргументов в подобных ситуациях (и риск того же характера).

Пример:

Вы можете создать функцию:

// DECLARATION:
// returns vector filled with items specified
std::vector<float> float_vector( size_t item_count = 0, ... /* floats */ );

// DEFINITION:
std::vector<float> float_vector( size_t item_count, ... )
{
    std::vector<float> vec;
    va_list ap;

    va_start(ap, item_count);
    for( ; item_count > 0; --item_count )
    {
        vec.push_back( va_arg(ap,float) );
    }
    va_end(ap);
    return vec;
}

Obvoiusly float_vector() возвращает пустой вектор, поскольку он эквивалентен float_vector(0).Во всех остальных случаях float_vector ведет себя как обычная функция с переменным числом аргументов.

...