diff --git a/.gitignore b/.gitignore index 9e79b4d..751d24b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ *.o .*.swp +raw_ptr +smart_ptr +smart_ptr_iterable diff --git a/Makefile b/Makefile index 6d59d74..1150842 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,9 @@ -run: wrappers - ./wrappers +run: all + ./raw_ptr + ./smart_ptr + ./iterable -wrappers: main.c - g++ -Wall -o wrappers main.c +all: raw_ptr smart_ptr iterable clean: - rm -f *.o wrappers + rm -f *.o raw_ptr smart_ptr iterable diff --git a/README.md b/README.md new file mode 100644 index 0000000..28e37b4 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +Wrappers and iterators examples +=============================== + +Build and run: + +``` +make +``` + +`raw_ptr.cc` +------------ + +Simply raw pointer wrapper. Shows how we can do an object abilities extension in the runtime. Useful for iterators. + +`smart_ptr.cc` +-------------- + +Similar example, but holds the shared pointer. + +`iterable.cc` +------------- + +Finally, the iterable with traversing algorithm compile-time instantiated. The template method returns an iterable object, which iterates over IShape's with its `.get_next()`/`.get_prev()`. + diff --git a/iterable b/iterable new file mode 100755 index 0000000..c5edc7c Binary files /dev/null and b/iterable differ diff --git a/iterable.cc b/iterable.cc new file mode 100644 index 0000000..6d0cda1 --- /dev/null +++ b/iterable.cc @@ -0,0 +1,23 @@ +#include +#include + +#include "main.h" + +int main() { + auto c1 = std::make_shared(3.0); + auto c2 = std::make_shared(5.0); + auto c3 = std::make_shared(7.0); + + c1->set_next(c2.get()); + c2->set_next(c3.get()); + + std::cout << "Forward:\n"; + for (auto& shape : c1->traverse()) { + shape.draw(); + } + + std::cout << "\nBackward:\n"; + for (auto& shape : c1->traverse()) { + shape.draw(); + } +} diff --git a/iterators.h b/iterators.h new file mode 100644 index 0000000..43e27e1 --- /dev/null +++ b/iterators.h @@ -0,0 +1,68 @@ +#pragma once + +template +class Iterator { +protected: + T* current; +public: + explicit Iterator(T* ptr) : current(ptr) {} + + T& operator*() const { return *current; } + T* operator->() const { return current; } + + bool operator!=(const Iterator& other) const { + return current != other.current; + } + + virtual Iterator& operator++() = 0; +}; + +template +class Traversal { + T* start; + +public: + explicit Traversal(T* start) : start(start) {} + + Policy begin() const { return Policy(start); } + Policy end() const { return Policy(nullptr); } +}; + +template +struct IteratorForward : public Iterator { + explicit IteratorForward(T* ptr) : Iterator(first(ptr)) {} + + static T* first(T* node) { + return node; + } + + static T* next(T* node) { + return node ? node->get_next() : nullptr; + } + + Iterator& operator++() override { + this->current = next(this->current); + return *this; + } +}; + +template +struct IteratorBackward : public Iterator { + explicit IteratorBackward(T* ptr) : Iterator(first(ptr)) {} + + static T* first(T* node) { + if (!node) return nullptr; + while (node->get_next()) node = node->get_next(); + return node; + } + + static T* next(T* node) { + return node ? node->get_prev() : nullptr; + } + + Iterator& operator++() override { + this->current = next(this->current); + return *this; + } +}; + diff --git a/main.h b/main.h new file mode 100644 index 0000000..5a3339e --- /dev/null +++ b/main.h @@ -0,0 +1,43 @@ +#pragma once + +#include "iterators.h" + +class IShape { + IShape* next = nullptr; + IShape* prev = nullptr; + +public: + virtual ~IShape() = default; + virtual void draw() const = 0; + virtual double area() const = 0; + + void set_next(IShape* n) { + next = n; + if (n) n->prev = this; + } + + IShape* get_next() const { return next; } + IShape* get_prev() const { return prev; } + + template + Traversal traverse() { + return Traversal(this); + } + + using forward = IteratorForward; + using backward = IteratorBackward; +}; + +class Circle : public IShape { + double r; +public: + Circle(double radius) : r(radius) {} + + void draw() const override { + std::cout << "Drawing Circle of radius " << r << "\n"; + } + + double area() const override { + return 3.14159 * r * r; + } +}; diff --git a/main.c b/raw_ptr.cc similarity index 62% rename from main.c rename to raw_ptr.cc index f4a8e19..bbf2f0d 100644 --- a/main.c +++ b/raw_ptr.cc @@ -1,17 +1,5 @@ #include - -struct IShape { - virtual void draw() const = 0; - virtual ~IShape() = default; -}; - -class Circle : public IShape { -public: - void draw() const override { - std::cout << "Circle::draw()\n"; - } -}; - +#include "main.h" template class Wrapper { @@ -39,12 +27,12 @@ void render_shape_by_ref(IShape& shape) { } int main() { - Circle c; - Wrapper w(&c); + Circle circle {10}; + Wrapper wrapped(&circle); - w->draw(); + std::cout << wrapped->area() << "\n"; - render_shape_by_ptr(w); + render_shape_by_ptr(wrapped); - render_shape_by_ref(w); + render_shape_by_ref(wrapped); } diff --git a/smart_ptr.cc b/smart_ptr.cc new file mode 100644 index 0000000..a91e93c --- /dev/null +++ b/smart_ptr.cc @@ -0,0 +1,44 @@ +#include +#include +#include "main.h" + +template +class Wrapper { + std::shared_ptr impl; + +public: + explicit Wrapper(std::shared_ptr ptr) : impl(std::move(ptr)) {} + + T* operator->() { return impl.get(); } + const T* operator->() const { return impl.get(); } + + std::shared_ptr get() const { return impl; } + + operator std::shared_ptr() const { return impl; } + operator const std::shared_ptr&() const { return impl; } + operator std::shared_ptr&() { return impl; } + + void myHelper() const { + std::cout << "[Wrapper] Helper method called\n"; + } +}; + +void draw_shape(const std::shared_ptr& shape) { + shape->draw(); +} + +int main() { + auto circle = std::make_shared(10.0); + Wrapper wrapped(circle); + + wrapped->draw(); + + std::cout << "Area: " << wrapped->area() << "\n"; + + wrapped.myHelper(); + + draw_shape(wrapped); + + std::shared_ptr copy = wrapped; + draw_shape(copy); +}