c++classc++20class-template

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


I'm trying solve Exercise 17-1 in "Beginning C++20: from invoice to professional" by Ivor Horton. It ask me to implement a "push_back()" function (resembles the one in std::vector) in the self-defined template class "MyArray".

The following is the class template:

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

The following are the implementation of the list initializer constructor and push_back() function:

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

I'm testing this template with:

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

Other member functions are working fine.

However, when I uncomment the List initializer constructor, the compiler will raise an error C298 - Element '1': conversion from size_t to 'T' requires a narrowing conversion

and a warning C4267 - conversion from 'size_t' to 'T', possible loss of data on "push_back()".

Am I missing something here ?


Solution

  • MyArray<T> copy { m_size + 1 }; If you uncomment the constructor with the initializer list, then it will be chosen in the copy declaration, T is unsigned int and size_t will possibly loose data. If you want to use the constructor with the size_t parameter, then declare the MyArray<T> copy(m_size + 1);.

    See the similar std::vector notes.

    Note that the presence of list-initializing constructor means list initialization and direct initialization do different things