Список аргументов переменной длины - Как понять, что мы получили последний аргумент? - PullRequest
4 голосов
/ 10 января 2011

У меня есть класс Polynomial, который содержит коэффициенты данного многочлена.
Предполагается, что один из перегруженных конструкторов получит эти коэффициенты через список переменных аргументов.

template <class T>
Polynomial<T>::Polynomial(T FirstCoefficient, ...)
{
    va_list ArgumentPointer;
    va_start(ArgumentPointer, FirstCoefficient);
    T NextCoefficient = FirstCoefficient;
    std::vector<T> Coefficients;
    while (true)
    {
        Coefficients.push_back(NextCoefficient);
        NextCoefficient = va_arg(ArgumentPointer, T);
        if (/* did we retrieve all the arguments */) // How do I implement this?
        {
            break;
        }
    }
    m_Coefficients = Coefficients;
}

Я знаю, что мы обычно передаем дополнительный параметр, который сообщает методу-получателю общее количество параметров, или мы передаем сентиментальный конечный параметр. Но для краткости и чистоты я не предпочитаю передавать дополнительный параметр.

Есть ли способ сделать это без изменения сигнатуры метода в примере?

Ответы [ 2 ]

8 голосов
/ 10 января 2011

В общем, нет, нет способа узнать, когда вы нажали последний аргумент, и вам нужно будет предоставить своего рода стража.По этой причине списки аргументов переменной длины небезопасны;нет никакого способа статически проверить, что все аргументы были получены правильно, или что они имеют правильные типы и т. д. Если вы посмотрите на большинство функций varargs, у них всех есть некоторый способ узнать, сколько существует аргументов.printf и scanf используют строку форматирования, open определяет тип операции и т. Д.

Однако в C ++ 0x вы сможете сделать это с помощью std::initializer_list, которая является более умной, более безопасной для типов альтернативой varargs.Например:

template <class T>
Polynomial<T>::Polynomial(T FirstCoefficient, std::initializer_list<T> coeffs)
{
    m_coefficients.insert(m_coefficients.begin(), coeffs.begin(), coeffs.end());
}

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

2 голосов
/ 10 января 2011

Нет, и это касается всех структур данных (список аргументов - это просто другая структура данных). У вас есть 3,5 варианта:

  1. Статическая заданная длина.
  2. Значение Стража.
  3. Структура данных включает в себя ее длину.
    3.5. Структура данных по своей природе обеспечивает некоторый способ безопасного определения длины до того, как вы достигнете конца структуры данных.

Независимо от того, что ваше решение будет сводиться к одному из этих вариантов.

...