add iterable
parent
765bfc3502
commit
2935b29e2e
@ -1,2 +1,5 @@
|
||||
*.o
|
||||
.*.swp
|
||||
raw_ptr
|
||||
smart_ptr
|
||||
smart_ptr_iterable
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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()`.
|
||||
|
||||
@ -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;
|
||||
}
|
||||
};
|
||||
@ -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…
Reference in New Issue