可变长度参数列表 - 如何理解我们检索到的最后一个参数?

时间:2011-01-09 21:41:17

标签: c++ variadic-functions

我有一个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 个答案:

答案 0 :(得分:8)

一般来说,不,没有办法知道你什么时候打到最后一个参数,你需要提供某种哨兵。由于这个原因,可变长度参数列表本质上是不安全的;没有办法静态检查所有参数是否已正确接收,或者它们是否具有正确的类型等。如果你看一下大多数varargs函数,它们都有一些方法可以知道有多少参数。 printfscanf使用格式化字符串,open查看操作类型等。

但是,在C ++ 0x中,您将能够使用std::initializer_list执行此操作,template <class T> Polynomial<T>::Polynomial(T FirstCoefficient, std::initializer_list<T> coeffs) { m_coefficients.insert(m_coefficients.begin(), coeffs.begin(), coeffs.end()); } 是varargs的更智能,更类型安全的替代方法。例如:

T

编译器现在可以键入 - 检查所有参数是否都有{{1}}类型,并为您完成所有范围检查。

答案 1 :(得分:2)

不,这适用于所有数据结构(参数列表只是另一种数据结构)。您有3.5个选项:

  1. 静态,预定长度。
  2. Sentinel值。
  3. 数据结构包括其长度。
    3.5。在到达数据结构的末尾之前,数据结构本身就提供了一些安全地获取长度的方法。
  4. 无论如何,您的解决方案将归结为其中一个选项。