#include <iostream>
#include <memory>
using namespace std;

template <typename T>
class Array
{
public:
    explicit Array(size_t size, const T& value = T()): size_(size), memory_(::operator new(size_*sizeof(T))
    {
        elements = new (memory_) T[size_];
        std::uninitialized_fill(elements, elements+size_, value);
    }
    // конструктор класса, который создает Array размера size, заполненный значениями value типа T. 
    // Если у класса нет конструктора по умолчанию, то второй аргумент этого конструктора обязателен.

    Array(): size_(0), elements(new T[0]){}
    //   конструктор класса, который можно вызвать без параметров. Должен создавать пустой Array.
  
    Array(const Array& other): size_(other.size_), memory_(::operator new (size_*sizeof(T)))
    {
        elements = new (memory_) T[size_];
        std::uninitialized_copy(other.elements, other.elements + size_, elements);
    }
    //   конструктор копирования, который создает копию параметра. Для типа T оператор присваивания не определен.

    ~Array()
    {
        for(size_t i = 0; i!=size_;++i)
            elements[i].~T();
        ::operator delete[](elements);
    }
    //   деструктор, если он вам необходим.
    
    Array& operator=(const Array& other)
    {
        if(this==&other) return *this;
        
        for(size_t i = 0; i!=size_;++i)
            elements[i].~T();
        ::operator delete[](memory_);

        memory_ = ::operator new(other.size_);
        elements = new (memory_) T[other.size_];
        std::uninitialized_copy(other.elements, other.elements + size_, elements);
        size_ = other.size_;
        return *this;
    }
    //   оператор присваивания.
        
    size_t size() const { return size_; }
    //   возвращает размер массива (количество элементов).

    T& operator[](size_t index) { return elements[index]; }
    const T& operator[](size_t index) const { return elements[index]; }
    //   две версии оператора доступа по индексу.
private:
    size_t size_;
    char* memory_;
    T* elements;
};

int main() {
	Array<float> ololo{};
	Array<float> psh(12, 321.099f);
	std::cout << "psh[10] = " << psh[10] << '\n';
	return 0;
}