diff options
Diffstat (limited to 'c/util.h')
-rw-r--r-- | c/util.h | 60 |
1 files changed, 35 insertions, 25 deletions
@@ -19,42 +19,49 @@ _Exit(1); \ }) +/* Scope guard. */ template <typename F> struct Finally { F f; - inline Finally(F f) : f(f) {} + inline Finally(F f) noexcept : f(f) {} inline ~Finally() { f(); } }; #define FINALLY Finally _ = [=]() template <typename T> -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 <typename T, auto F = Delete<T>> 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<T>& s) : data(s.data()), c(s.capacity()) {} - template <size_t N> 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<T> operator +(size_t i) { return {data+i, c-i}; } + Buf(T* data, size_t c) noexcept : data(data), c(c) {} + Buf(std::basic_string<T>& s) noexcept : data(s.data()), c(s.capacity()) {} + template <size_t N> 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<T> operator +(size_t i) noexcept { return {data+i, c-i}; } //T operator -(size_t i) { return {data-i, c+i}; } }; |