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 ?
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