#ifndef ARRAY_HPP #define ARRAY_HPP #include #include #include #include #include #include #include "assert.hpp" template class Array { private: using Tag = enum {AllocateStorage}; Array(Tag tag, std::size_t size) : size(size), data(size > 0? static_cast(operator new(sizeof(T) * size)) : nullptr) { } public: Array() noexcept : size(0), data(nullptr) { } Array(std::size_t size) : Array(AllocateStorage, size) { for (std::size_t index = 0; index < size; ++index) { new (data + index) T(); } } Array(std::size_t size, const T& t) : Array(AllocateStorage, size) { for (std::size_t index = 0; index < size; ++index) { new (data + index) T(t); } } template Array(Iterator it1, Iterator it2) : Array(AllocateStorage, std::distance(it1, it2)) { std::size_t index = 0; while (it1 != it2 && index < size) { new (data + index++) T(*it1++); } size = index; // just in case } Array(std::initializer_list elements) : Array(elements.begin(), elements.end()) { } Array(const Array& other) : Array(AllocateStorage, other.size) { for (std::size_t index = 0; index < size; ++index) { new (data + index) T(other.data[index]); } } friend void swap(Array& a1, Array& a2) noexcept { using std::swap; swap(a1.size, a2.size); swap(a1.data, a2.data); } Array(Array&& other) noexcept : Array() { swap(*this, other); } ~Array() { for (std::size_t index = 0; index < size; ++index) { data[index].~T(); } operator delete(data); } Array& operator=(Array other) noexcept { swap(*this, other); return *this; } std::size_t get_size() const noexcept { return size; } T& operator()(std::size_t index) noexcept { ASSERT(index < size); return data[index]; } const T& operator()(std::size_t index) const noexcept { ASSERT(index < size); return data[index]; } T* begin() noexcept { return data; } const T* begin() const noexcept { return data; } T* end() noexcept { return data + size; } const T* end() const noexcept { return data + size; } private: std::size_t size; T* data; }; #endif