#include <iostream>
#include <memory>
#include <vector>
class FileHandle {
FILE* file;
public:
explicit FileHandle(const char* filename, const char* mode = "r")
: file(std::fopen(filename, mode)) {
if (!file) throw std::runtime_error("Failed to open file");
}
~FileHandle() {
if (file) std::fclose(file);
}
FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
FileHandle(FileHandle&& other) noexcept : file(other.file) {
other.file = nullptr;
}
FILE* get() const { return file; }
};
template<typename T>
class SharedBuffer {
std::shared_ptr<std::vector<T>> data;
size_t offset;
size_t length;
public:
explicit SharedBuffer(size_t size)
: data(std::make_shared<std::vector<T>>(size)),
offset(0), length(size) {}
SharedBuffer slice(size_t start, size_t len) const {
SharedBuffer result(*this);
result.offset = offset + start;
result.length = len;
return result;
}
T& operator[](size_t index) {
return (*data)[offset + index];
}
size_t size() const { return length; }
size_t use_count() const { return data.use_count(); }
};
template<typename T>
class UniqueArray {
std::unique_ptr<T[]> data;
size_t len;
public:
explicit UniqueArray(size_t size) : data(std::make_unique<T[]>(size)), len(size) {}
T& operator[](size_t index) { return data[index]; }
const T& operator[](size_t index) const { return data[index]; }
size_t size() const { return len; }
T* begin() { return data.get(); }
T* end() { return data.get() + len; }
std::unique_ptr<T[]> release() { return std::move(data); }
};
class Observable {
std::vector<std::weak_ptr<class Observer>> observers;
public:
void add_observer(std::shared_ptr<Observer> observer) {
observers.push_back(observer);
}
void notify(const std::string& message) {
observers.erase(
std::remove_if(observers.begin(), observers.end(),
[](const std::weak_ptr<Observer>& wp) { return wp.expired(); }),
observers.end()
);
for (auto& wp : observers) {
if (auto sp = wp.lock()) {
sp->on_notify(message);
}
}
}
};
class Observer : public std::enable_shared_from_this<Observer> {
public:
virtual ~Observer() = default;
virtual void on_notify(const std::string& message) = 0;
};
class ConsoleObserver : public Observer {
public:
void on_notify(const std::string& message) override {
std::cout << "Console: " << message << "\n";
}
};
class TreeNode {
public:
int value;
std::shared_ptr<TreeNode> left;
std::shared_ptr<TreeNode> right;
std::weak_ptr<TreeNode> parent;
TreeNode(int v) : value(v) {}
void set_children(std::shared_ptr<TreeNode> l, std::shared_ptr<TreeNode> r) {
left = l;
right = r;
if (left) left->parent = shared_from_this();
if (right) right->parent = shared_from_this();
}
};
template<typename T>
class Factory {
public:
template<typename... Args>
std::shared_ptr<T> create(Args&&... args) {
return std::make_shared<T>(std::forward<Args>(args)...);
}
template<typename... Args>
std::unique_ptr<T> create_unique(Args&&... args) {
return std::make_unique<T>(std::forward<Args>(args)...);
}
};
void demonstrate_custom_deleter() {
auto file_deleter = [](FILE* f) {
if (f) {
std::cout << "Closing file\n";
std::fclose(f);
}
};
std::shared_ptr<FILE> file(std::fopen("test.txt", "w"), file_deleter);
if (file) {
std::fprintf(file.get(), "Hello from custom deleter\n");
}
}
void demonstrate_enable_shared_from_this() {
auto node = std::make_shared<TreeNode>(10);
auto left = std::make_shared<TreeNode>(5);
auto right = std::make_shared<TreeNode>(15);
node->set_children(left, right);
if (auto p = left->parent.lock()) {
std::cout << "Left child's parent value: " << p->value << "\n";
}
}
void demonstrate_circular_reference() {
struct Node {
int value;
std::shared_ptr<Node> next;
std::weak_ptr<Node> prev;
};
auto a = std::make_shared<Node>();
auto b = std::make_shared<Node>();
a->value = 1;
b->value = 2;
a->next = b;
b->prev = a;
std::cout << "a use_count: " << a.use_count() << "\n";
std::cout << "b use_count: " << b.use_count() << "\n";
}
template<typename T>
std::shared_ptr<T> make_shared_array(size_t size) {
return std::shared_ptr<T>(new T[size], std::default_delete<T[]>());
}
int main() {
SharedBuffer<int> buffer(100);
for (size_t i = 0; i < buffer.size(); ++i) {
buffer[i] = static_cast<int>(i);
}
auto slice = buffer.slice(10, 20);
std::cout << "Slice size: " << slice.size() << "\n";
std::cout << "Slice[0]: " << slice[0] << "\n";
std::cout << "Buffer use_count: " << buffer.use_count() << "\n";
demonstrate_circular_reference();
demonstrate_custom_deleter();
return 0;
}