add iterable

master
Sergey Marinkevich 5 months ago
parent 765bfc3502
commit 2935b29e2e

3
.gitignore vendored

@ -1,2 +1,5 @@
*.o *.o
.*.swp .*.swp
raw_ptr
smart_ptr
smart_ptr_iterable

@ -1,8 +1,9 @@
run: wrappers run: all
./wrappers ./raw_ptr
./smart_ptr
./iterable
wrappers: main.c all: raw_ptr smart_ptr iterable
g++ -Wall -o wrappers main.c
clean: clean:
rm -f *.o wrappers rm -f *.o raw_ptr smart_ptr iterable

@ -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()`.

Binary file not shown.

@ -0,0 +1,23 @@
#include <iostream>
#include <memory>
#include "main.h"
int main() {
auto c1 = std::make_shared<Circle>(3.0);
auto c2 = std::make_shared<Circle>(5.0);
auto c3 = std::make_shared<Circle>(7.0);
c1->set_next(c2.get());
c2->set_next(c3.get());
std::cout << "Forward:\n";
for (auto& shape : c1->traverse<IShape::forward>()) {
shape.draw();
}
std::cout << "\nBackward:\n";
for (auto& shape : c1->traverse<IShape::backward>()) {
shape.draw();
}
}

@ -0,0 +1,68 @@
#pragma once
template <typename T>
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<typename T, typename Policy>
class Traversal {
T* start;
public:
explicit Traversal(T* start) : start(start) {}
Policy begin() const { return Policy(start); }
Policy end() const { return Policy(nullptr); }
};
template <typename T>
struct IteratorForward : public Iterator<T> {
explicit IteratorForward(T* ptr) : Iterator<T>(first(ptr)) {}
static T* first(T* node) {
return node;
}
static T* next(T* node) {
return node ? node->get_next() : nullptr;
}
Iterator<T>& operator++() override {
this->current = next(this->current);
return *this;
}
};
template <typename T>
struct IteratorBackward : public Iterator<T> {
explicit IteratorBackward(T* ptr) : Iterator<T>(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<T>& operator++() override {
this->current = next(this->current);
return *this;
}
};

@ -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<typename Policy>
Traversal<IShape, Policy> traverse() {
return Traversal<IShape, Policy>(this);
}
using forward = IteratorForward<IShape>;
using backward = IteratorBackward<IShape>;
};
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;
}
};

@ -1,17 +1,5 @@
#include <iostream> #include <iostream>
#include "main.h"
struct IShape {
virtual void draw() const = 0;
virtual ~IShape() = default;
};
class Circle : public IShape {
public:
void draw() const override {
std::cout << "Circle::draw()\n";
}
};
template<typename T> template<typename T>
class Wrapper { class Wrapper {
@ -39,12 +27,12 @@ void render_shape_by_ref(IShape& shape) {
} }
int main() { int main() {
Circle c; Circle circle {10};
Wrapper<IShape> w(&c); Wrapper<IShape> 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);
} }

@ -0,0 +1,44 @@
#include <iostream>
#include <memory>
#include "main.h"
template<typename T>
class Wrapper {
std::shared_ptr<T> impl;
public:
explicit Wrapper(std::shared_ptr<T> ptr) : impl(std::move(ptr)) {}
T* operator->() { return impl.get(); }
const T* operator->() const { return impl.get(); }
std::shared_ptr<T> get() const { return impl; }
operator std::shared_ptr<T>() const { return impl; }
operator const std::shared_ptr<T>&() const { return impl; }
operator std::shared_ptr<T>&() { return impl; }
void myHelper() const {
std::cout << "[Wrapper] Helper method called\n";
}
};
void draw_shape(const std::shared_ptr<IShape>& shape) {
shape->draw();
}
int main() {
auto circle = std::make_shared<Circle>(10.0);
Wrapper<IShape> wrapped(circle);
wrapped->draw();
std::cout << "Area: " << wrapped->area() << "\n";
wrapped.myHelper();
draw_shape(wrapped);
std::shared_ptr<IShape> copy = wrapped;
draw_shape(copy);
}
Loading…
Cancel
Save