#include #include #include #include template class dynamic_array { private: std::shared_ptr data {}; size_t n {}; public: dynamic_array(size_t n) { this -> n = n; data = std::make_shared(n); } dynamic_array(const dynamic_array& other) { n = other.n; data = std::make_shared(n); /* Here we perform a deep copy */ for (size_t i {}; i < n; ++i) data[i] = other[i]; } T& operator[](int index) { return data.get() + index; } const T& operator[](int index) const { return data[index]; } T& at(size_t index) { if (index < n) return data[index]; throw "Index out of range"; } size_t size() const { return n; } ~dynamic_array() = default; std::shared_ptr begin() { return data; } const std::shared_ptr begin() const { return data; } std::shared_ptr end() { return data + n; } const std::shared_ptr end() const { return data + n; } friend dynamic_array operator+(const dynamic_array& arr1, dynamic_array& arr2) { dynamic_array result(arr1.size() + arr2.size()); std::copy(arr1.begin(), arr1.end(), result.begin()); std::copy(arr2.begin(), arr2.end(), result.begin() + arr1.size()); return result; } std::string to_string(const std::string& sep = ", ") { if (n == 0) return ""; std::ostringstream os {}; os << data.get(); for (size_t i {1}; i < n; ++i) os << sep << data.get() + i; return os.str(); } }; struct student { std::string name {}; size_t standard {}; }; std::ostream& operator<<(std::ostream& os, const student& s) { return (os << "[Name: " << s.name << ", Standard: " << s.standard << "]"); } int main() { size_t nStudents {}; std::cout << "Enter number of students in class 1: "; std::cin >> nStudents; dynamic_array class1(nStudents); for (size_t i {}; i < nStudents; ++i) { std::cout << "Enter name and class of student " << i + 1 << ": "; std::string name {}; size_t standard {}; std::cin >> name >> standard; class1[i] = student {name, standard}; } // Now, let's tro to access the student out of range in the array try { class1[nStudents] =student{"John", 8}; // No exception, endeffined behaviour std::cout << "class1 student set out of range without exception" << std::endl; class1.at(nStudents) = student{"John", 8}; // Will throw exception } catch(...) { std::cout << "Exception caught" << std::endl; } auto class2 = class1; // Deep copy std::cout << "Second class after initialized using first array: " << class2.to_string() << std::endl; auto class3 = class1 + class2; // Combines both classes and creates a bigger one std::cout << "Combined class: "; std::cout << class3.to_string() << std::endl; return 0; }