Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable length argument list - How to understand we retrieved the last argument?

I have a Polynomial class which holds coefficients of a given polynomial.
One of its overloaded constructors is supposed to receive these coefficients via variable argument list.

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;
}

I know that we usually pass an extra parameter which tells the recipient method the total number of parameters, or we pass a sentimental ending parameter. But in order to keep thing short and clean, I don't prefer passing an extra parameter.

Is there any way of doing this without modifying the method signature in the example?

like image 909
hkBattousai Avatar asked Dec 29 '22 03:12

hkBattousai


1 Answers

In general, no, there's no way to know when you've hit the last argument and you'll need to provide some sort of sentinel. Variable-length argument lists are inherently unsafe for this reason; there's no way to statically check that all the arguments have been received correctly, or that they have the right types, etc. If you take a look at most varargs functions, they all have some way of knowing how many arguments there are. printf and scanf use the formatting string, open looks at the type of operation, etc.

In C++0x, however, you'll be able to do this using std::initializer_list, which is a smarter, more type-safe alternative to varargs. For example:

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

The compiler can now type-check that all the arguments have type T and will do all the range-checking for you.

like image 114
templatetypedef Avatar answered Feb 04 '23 04:02

templatetypedef