aboutsummaryrefslogtreecommitdiff
path: root/c/util.h
diff options
context:
space:
mode:
Diffstat (limited to 'c/util.h')
-rw-r--r--c/util.h60
1 files changed, 35 insertions, 25 deletions
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 <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}; }
};