为什么在使用模板和stdarg函数时,float会被提升为double?

4
我创建了一个模板类Array: 下面是必要的代码:
#ifndef ARRAY_H
#define ARRAY_H
#include <iostream>
#include <cstdarg>

template< typename T >
class Array
{
public:
    Array(size_t length = 0, ...);
    ~Array();
private:
    T *m_values;
    size_t m_len;
};

template< typename T>
Array< T >::Array(size_t len, ...) : m_values(0), m_len(len)
{
    if(len != 0)
    {
        m_values = new T[len];
        va_list ap;
        va_start(ap, len);
        for(size_t i(0); i < len; i++)
            m_values[i] = va_arg(ap, T);
        va_end(ap);
    }
    else
        m_values = NULL;
}

template< typename T >
Array< T >::~Array()
{
    delete[] m_values;
}

#endif // ARRAY_H

这是我的主函数

,与IT技术有关。
int main()
{
    Array<float> a;
    return 0;
}

当我编译代码时,出现了一个警告:"float is promoted to double when passed through (...)". 这意味着问题源自于一个接受未知数量参数的构造函数。为什么编译器会将 float 提升为 double?有没有解决方法,或者我必须专门为 float 版本设计类?此外,如何确定编译器是否会改变其他类型...

这就是它们的工作方式。传递到省略号中的参数被指定为被提升。由于这是C++,您可以使用std :: initializer_list <float>代替。 - chris
...... 要求所有参数都在栈上。我猜测你的编译器使用FPU传递float值,因此使得float与va_arg()不兼容。另外,你为什么不想使用std::vector呢? - Remy Lebeau
请参见:https://dev59.com/R2gu5IYBdhLWcg3wgnVh - PaulMcKenzie
通过 ... 传递参数总是会将 float 提升为 double。请使用 initializer_list - T.C.
此外,您的Array类几乎没有任何用处,并且使用“...”使情况更糟。例如,尝试创建一个Array<std::string>。相反,请使用std::vector - PaulMcKenzie
虽然有点离题,但如果你用 std::vector<T> m_values 替换 T *m_values; size_t m_len;,你将节省大部分开发时间(并且可能获得更好的性能)。 - M.M
1个回答

6
当调用具有可变长参数列表的函数时,变量参数使用C语言的旧的默认参数升级方式传递。这些规则指出类型charshort int会自动升级为int,而类型float会自动升级为double 因此,可变参数函数绝不能接收charshort intfloat类型的参数。

不错的答案,但它看起来非常像 https://www.eskimo.com/~scs/cclass/int/sx11c.html,在页脚中的日期表明该答案比那篇文章早几十年。 - giordano

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接