#include <iostream>
#include <stdexcept>
#include <algorithm>
#include <utility>
namespace my {
template <typename T, size_t N>
class array {
public:
using value_type = T;
using reference_type = value_type&;
using const_reference = const value_type&;
using pointer_type = value_type*;
using const_pointer = const value_type*;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using iterator = pointer_type;
using const_iterator = const_pointer;
template <typename ItType>
class ReverseIterator {
private:
ItType _it;
public:
ReverseIterator(ItType it): _it(it) {}
ReverseIterator& operator++() {
--_it;
return *this;
}
decltype(*_it) operator*() {
return *_it;
}
bool operator!=(const ReverseIterator& other) const {
return this->_it != other._it;
}
};
using reverse_iterator = ReverseIterator<iterator>;
using const_reverse_iterator = ReverseIterator<const_iterator>;
value_type arr[N];
constexpr size_type size() const noexcept { return N; }
constexpr size_type max_size() const noexcept { return N; }
constexpr bool empty() const noexcept {
return N == 0;
}
reference_type at(size_type pos) {
if (pos > N - 1)
throw std::out_of_range(
"my::array::at(): array index out of range"
);
return arr[pos];
}
reference_type operator[](size_type pos) {
return arr[pos];
}
reference_type front() { return arr[0]; }
reference_type back() { return arr[N - 1]; }
pointer_type data() noexcept {
return arr;
}
void fill(const_reference value) {
for (size_type i = 0; i < N; ++i)
arr[i] = value;
}
void swap(array& other) {
for (size_type i = 0; i < N; ++i) {
value_type tmp = other.arr[i];
other.arr[i] = this->arr[i];
this->arr[i] = std::move(tmp);
}
}
iterator begin() noexcept { return arr; }
iterator end() noexcept { return arr + N; }
const_iterator cbegin() const noexcept { return arr; }
const_iterator cend() const noexcept { return arr + N; }
reverse_iterator rbegin() noexcept {
return ReverseIterator<iterator>(arr + N - 1);
}
reverse_iterator rend() noexcept {
return ReverseIterator<iterator>(arr - 1);
}
const_reverse_iterator crbegin()const noexcept {
return ReverseIterator<const_iterator>(arr + N - 1);
}
const_reverse_iterator crend() const noexcept {
return ReverseIterator<const_iterator>(arr - 1);
}
};
}
template <typename T, size_t N>
void print_array(my::array<T, N> arr) {
std::cout << "{ ";
for (const int& i: arr) {
std::cout << i << ' ';
}
std::cout << "}\n";
}
int main() {
my::array<int, 10> arr { 7, 3, 8, 1, 0, 2, 9, 5, 6, 4 };
std::cout << "arr: ";
print_array(arr);
std::cout << "arr reversed: ";
std::cout << "{ ";
for(auto it = arr.rbegin(); it != arr.rend(); ++it) {
std::cout << *it << " ";
}
std::cout << "}\n";
std::cout << "Size of the array: " << arr.size() << '\n';
std::cout << "First element of the array: " << arr.front() << '\n';
std::cout << "Last element of the array: " << arr.back() << '\n';
std::sort(arr.begin(), arr.end());
std::cout << "arr sorted: ";
print_array(arr);
my::array<int, 10> arr2;
arr2.fill(0);
arr.swap(arr2);
std::cout << "arr : ";
print_array(arr);
std::cout << "arr2: ";
print_array(arr2);
try {
arr.at(10);
} catch (const std::out_of_range& e) {
std::cout << "Error: " << e.what() << '\n';
}
return 0;
}