add observer_ptr.h
authorJacob Lifshay <programmerjake@gmail.com>
Sat, 28 Oct 2017 08:02:06 +0000 (01:02 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Sat, 28 Oct 2017 08:02:06 +0000 (01:02 -0700)
src/util/observer_ptr.h [new file with mode: 0644]

diff --git a/src/util/observer_ptr.h b/src/util/observer_ptr.h
new file mode 100644 (file)
index 0000000..39f33c9
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2017 Jacob Lifshay
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+#ifndef UTIL_OBSERVER_PTR_H_
+#define UTIL_OBSERVER_PTR_H_
+
+#include <cstddef>
+#include <type_traits>
+#include <functional>
+#include <utility>
+
+namespace kazan
+{
+namespace util
+{
+template <typename T>
+class observer_ptr
+{
+public:
+    typedef T element_type;
+
+private:
+    T *value;
+
+public:
+    constexpr observer_ptr() noexcept : value(nullptr)
+    {
+    }
+    constexpr observer_ptr(std::nullptr_t) noexcept : value(nullptr)
+    {
+    }
+    explicit constexpr observer_ptr(T *value) noexcept : value(value)
+    {
+    }
+    template <typename T2,
+              typename = typename std::enable_if<std::is_convertible<T2 *, T *>::value>::type>
+    observer_ptr(observer_ptr<T2> rt) noexcept : value(rt.get())
+    {
+    }
+    constexpr T *release() noexcept
+    {
+        T *retval = value;
+        value = nullptr;
+        return retval;
+    }
+    constexpr void reset(T *new_value = nullptr) noexcept
+    {
+        value = new_value;
+    }
+    constexpr void swap(observer_ptr &other) noexcept
+    {
+        T *temp = value;
+        value = other.value;
+        other.value = temp;
+    }
+    constexpr T *get() const noexcept
+    {
+        return value;
+    }
+    constexpr explicit operator bool() const noexcept
+    {
+        return value != nullptr;
+    }
+    constexpr typename std::add_lvalue_reference<T> operator*() const noexcept
+    {
+        return *value;
+    }
+    constexpr T *operator->() const noexcept
+    {
+        return value;
+    }
+    constexpr explicit operator T *() const noexcept
+    {
+        return value;
+    }
+};
+
+template <typename T>
+constexpr observer_ptr<T> make_observer(T *value) noexcept
+{
+    return observer_ptr<T>(value);
+}
+
+template <typename T1, typename T2>
+constexpr bool operator==(const observer_ptr<T1> &l, const observer_ptr<T2> &r) noexcept
+{
+    return l.get() == r.get();
+}
+
+template <typename T1, typename T2>
+constexpr bool operator!=(const observer_ptr<T1> &l, const observer_ptr<T2> &r) noexcept
+{
+    return !(l == r);
+}
+
+template <typename T>
+constexpr bool operator==(const observer_ptr<T> &p, std::nullptr_t) noexcept
+{
+    return !p;
+}
+
+template <typename T>
+constexpr bool operator==(std::nullptr_t, const observer_ptr<T> &p) noexcept
+{
+    return !p;
+}
+
+template <typename T>
+constexpr bool operator!=(const observer_ptr<T> &p, std::nullptr_t) noexcept
+{
+    return static_cast<bool>(p);
+}
+
+template <typename T>
+constexpr bool operator!=(std::nullptr_t, const observer_ptr<T> &p) noexcept
+{
+    return static_cast<bool>(p);
+}
+
+template <typename T1, typename T2>
+constexpr bool operator<(const observer_ptr<T1> &l, const observer_ptr<T2> &r) noexcept
+{
+    return std::less<typename std::common_type<T1 *, T2 *>::type>()(l.get(), r.get());
+}
+
+template <typename T1, typename T2>
+constexpr bool operator>(const observer_ptr<T1> &l, const observer_ptr<T2> &r) noexcept
+{
+    return r < l;
+}
+
+template <typename T1, typename T2>
+constexpr bool operator<=(const observer_ptr<T1> &l, const observer_ptr<T2> &r) noexcept
+{
+    return !(r < l);
+}
+
+template <typename T1, typename T2>
+constexpr bool operator>=(const observer_ptr<T1> &l, const observer_ptr<T2> &r) noexcept
+{
+    return !(l < r);
+}
+}
+}
+
+namespace std
+{
+template <typename T>
+constexpr void swap(kazan::util::observer_ptr<T> &l, kazan::util::observer_ptr<T> &r) noexcept
+{
+    l.swap(r);
+}
+
+template <typename T>
+struct hash<kazan::util::observer_ptr<T>>
+{
+    constexpr std::size_t operator()(kazan::util::observer_ptr<T> v) const noexcept
+    {
+        return std::hash<T *>()(v);
+    }
+};
+}
+
+#endif // UTIL_OBSERVER_PTR_H_