从“size_t”到“T”的转换需要缩小转换范围 - 类模板

Conversion from 'size_t' to 'T' Requires a Narrowing Conversion - Class Template

提问人:The Lonesome Coder 提问时间:10/24/2023 最后编辑:康桓瑋The Lonesome Coder 更新时间:10/24/2023 访问量:73

问:

我正在尝试解决 Ivor Horton 的“入门 C++20:从发票到专业”中的练习 17-1。它要求我在自定义模板类“MyArray”中实现一个“push_back()”函数(类似于 std::vector 中的函数)。

以下是类模板:

export module myArray;

import <initializer_list>;
import <stdexcept>;
import <utility>;

export template <typename T>
class MyArray
{
    public:

        MyArray();                                          // Default constructor
        MyArray(size_t size);                               // Constructor
        // MyArray(std::initializer_list<T> elements);       // List initializer constructor
        MyArray(const MyArray& another);                    // Copy constructor

        ~MyArray();                                         // Destructor

        MyArray& operator = (const MyArray& another);       // Copy assignment

        T& operator [] (size_t index);                      // Subscript operator
        const T& operator [] (size_t index) const;          // Subscript operator on const-array

        size_t getSize() const;                             // Getter

        void swap(MyArray& other) noexcept;                 // For copy-and-swap idiom

        void push_back(const T& newElement);                // Add new element to the array


    private:
        T* m_elements;
        size_t m_size;
};

以下是列表初始值设定项构造函数和 push_back() 函数的实现:

template <typename T>
MyArray<T>::MyArray(std::initializer_list<T> elements)
    : m_elements { new T[elements.size()] }, m_size { elements.size() }
{
    for (size_t i { 0 }; const T & element : elements)
    {
        m_elements[i] = element;
        ++i;
    }
}
template <typename T>
void MyArray<T>::push_back(const T& newElement)
{
    MyArray<T> copy { m_size + 1 };

    for (size_t i { 0 }; i < m_size; ++i)
    {
        copy[i] = m_elements[i];
    }

    copy[m_size] = newElement;

    swap(copy);
}

我正在测试这个模板:

import myArray;
import <iostream>;

int main()
{
    const unsigned numElements { 100 };

    MyArray<unsigned int> squares;       // default construction

    for (unsigned i {}; i < numElements; ++i)
    {
        squares.push_back(i * i);    // push_back()
    }


    std::cout << squares.getSize() << " squares were added." << std::endl;
    std::cout << "For instance: 13 squared equals " << squares[13] << std::endl;
}

其他成员函数工作正常。

但是,当我取消注释 List 初始值设定项构造函数时,编译器将引发 错误C298 - Element '1': conversion from size_t to 'T' requires a narrowing conversion

以及“push_back()”上的警告。C4267 - conversion from 'size_t' to 'T', possible loss of data

我在这里遗漏了什么吗?

C++ C++20 类模板

评论

1赞 273K 10/24/2023
请在单个代码块中发布一个最小的可重现示例。请将完整的错误消息与注释一起发布。
0赞 molbdnilo 10/24/2023
通常,使用不能与大小或索引混淆的元素来测试集合是一个好主意。 可能会给出更好的错误消息。MyArray<std::string>
0赞 The Lonesome Coder 10/24/2023
@273K 非常感谢!我很抱歉,这只是我第二次发布问题,下次还会这样做。
0赞 The Lonesome Coder 10/24/2023
@molbdnilo适当地注意到了!

答:

2赞 273K 10/24/2023 #1

MyArray<T> copy { m_size + 1 };如果使用初始值设定项列表取消对构造函数的注释,则它将在声明中被选中,并且可能会丢失数据。如果要将构造函数与参数一起使用,请声明 .copyTunsigned intsize_tsize_tMyArray<T> copy(m_size + 1);

请参阅类似的 std::vector 注释

请注意,列表初始化构造函数的存在意味着列表初始化和直接初始化执行不同的操作