From b9d7ec228b03e2978b0e1d9f21dadd56b2f405e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Mon, 29 Aug 2022 23:33:48 +0200 Subject: Small improvments. --- c/util.h | 60 +++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 25 deletions(-) (limited to 'c/util.h') diff --git a/c/util.h b/c/util.h index ffc6b57..f9e3057 100644 --- a/c/util.h +++ b/c/util.h @@ -19,42 +19,49 @@ _Exit(1); \ }) +/* Scope guard. */ template struct Finally { F f; - inline Finally(F f) : f(f) {} + inline Finally(F f) noexcept : f(f) {} inline ~Finally() { f(); } }; #define FINALLY Finally _ = [=]() template -inline void Delete(T v) +inline void Delete(T v) noexcept { delete v; } +/* Unique is similar to unique_ptr, but it is designed for pointers + * and handles of type T, where T is not an RAII class. Further, the + * managed object is assumed to be in an invalid state until checked + * with Good or Bad. Upon destruction, the object, if valid, is passed + * to a given destructor function F. */ template > struct Unique { - T v; - bool ok = true; - Unique() : ok(false) {} - Unique(T v) : v(v) {} - Unique& operator =(T v_) + union { T v; }; + bool ok = false; + Unique() noexcept {} + Unique(T v) noexcept : v(v) {} + Unique& operator =(T v_) noexcept { - if (ok) + if (ok) { F(v); + v.~T(); + } v = v_; - ok = true; + ok = false; return *this; } - Unique(Unique&& other) + Unique(Unique&& other) noexcept : v(std::move(other.v)), ok(other.ok) { - v = std::move(other.v); other.ok = false; } - Unique& operator =(Unique&& other) + Unique& operator =(Unique&& other) noexcept { if (ok) F(v); @@ -63,17 +70,20 @@ struct Unique other.ok = false; return *this; } - bool Not(T u) + bool Good(T u) noexcept { - if (v == u) - return ok = false; - else - return true; + return ok = v == u; + } + bool Bad(T u) noexcept + { + return ok = v != u; } ~Unique() { - if (ok) + if (ok) { F(v); + v.~T(); + } } }; @@ -83,13 +93,13 @@ struct Buf { T* data; size_t c; - Buf(T* data, size_t c) : data(data), c(c) {} - Buf(std::basic_string& s) : data(s.data()), c(s.capacity()) {} - template Buf(T (&data)[N]) : data(data), c(N) {} - operator T*() { return data; } - T& operator *() { return *data; } - T& operator [](size_t i) { return data[i]; } - Buf operator +(size_t i) { return {data+i, c-i}; } + Buf(T* data, size_t c) noexcept : data(data), c(c) {} + Buf(std::basic_string& s) noexcept : data(s.data()), c(s.capacity()) {} + template Buf(T (&data)[N]) noexcept : data(data), c(N) {} + operator T*() noexcept { return data; } + T& operator *() noexcept { return *data; } + T& operator [](size_t i) noexcept { return data[i]; } + Buf operator +(size_t i) noexcept { return {data+i, c-i}; } //T operator -(size_t i) { return {data-i, c+i}; } }; -- cgit v1.2.3