From 6c58f1e095f7dbe1e7e1654c1807a76276a2f3f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Smr=C5=BE?= Date: Sat, 5 Jun 2021 23:10:24 +0200 Subject: Contact list in shared state --- include/erebos/list.h | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 include/erebos/list.h (limited to 'include/erebos/list.h') diff --git a/include/erebos/list.h b/include/erebos/list.h new file mode 100644 index 0000000..f5f2d3f --- /dev/null +++ b/include/erebos/list.h @@ -0,0 +1,116 @@ +#pragma once + +#include +#include +#include +#include + +namespace erebos { + +using std::function; +using std::make_shared; +using std::make_unique; +using std::move; +using std::shared_ptr; +using std::unique_ptr; +using std::variant; + +template +class List +{ +public: + struct Nil { bool operator==(const Nil &) const { return true; } }; + struct Cons { + T head; List tail; + bool operator==(const Cons & x) const { return head == x.head && tail == x.tail; } + }; + + List(); + List(const T head, List tail); + + const T & front() const; + const List & tail() const; + + bool empty() const; + + bool operator==(const List &) const; + bool operator!=(const List &) const; + + List push_front(T x) const; + +private: + struct Priv; + shared_ptr p; +}; + +template +struct List::Priv +{ + variant value; + + function eval = {}; + mutable std::once_flag once = {}; +}; + +template +List::List(): + p(shared_ptr(new Priv { Nil() })) +{ + std::call_once(p->once, [](){}); +} + +template +List::List(T head, List tail): + p(shared_ptr(new Priv { + Cons { move(head), move(tail) } + })) +{ + std::call_once(p->once, [](){}); +} + +template +const T & List::front() const +{ + std::call_once(p->once, p->eval); + return std::get(p->value).head; +} + +template +const List & List::tail() const +{ + std::call_once(p->once, p->eval); + return std::get(p->value).tail; +} + +template +bool List::empty() const +{ + std::call_once(p->once, p->eval); + return std::holds_alternative(p->value); +} + +template +bool List::operator==(const List & other) const +{ + if (p == other.p) + return true; + + std::call_once(p->once, p->eval); + std::call_once(other.p->once, other.p->eval); + return p->value == other.p->value; + +} + +template +bool List::operator!=(const List & other) const +{ + return !(*this == other); +} + +template +List List::push_front(T x) const +{ + return List(move(x), *this); +} + +} -- cgit v1.2.3