summaryrefslogtreecommitdiff
path: root/src/player/backends/utility/optional.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/player/backends/utility/optional.h')
-rw-r--r--src/player/backends/utility/optional.h517
1 files changed, 517 insertions, 0 deletions
diff --git a/src/player/backends/utility/optional.h b/src/player/backends/utility/optional.h
new file mode 100644
index 0000000..9ee0b71
--- /dev/null
+++ b/src/player/backends/utility/optional.h
@@ -0,0 +1,517 @@
+//------------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------------
+# ifndef __TD__OPTIONAL_H__
+# define __TD__OPTIONAL_H__
+# pragma once
+
+# include <type_traits>
+# include <utility>
+# include <cassert>
+
+
+//------------------------------------------------------------------------------
+struct nullopt_t
+{
+ struct init {};
+ nullopt_t(init) {}
+};
+
+const nullopt_t nullopt((nullopt_t::init()));
+
+template <typename T>
+struct optional
+{
+private:
+ typedef typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type storage_type;
+
+ typedef void (optional::*bool_type)() const;
+ void safe_bool() const { }
+
+
+public:
+ optional();
+ optional(nullopt_t);
+ optional(const optional& v);
+ optional(optional&& v);
+ optional(const T& v);
+ optional(T&& v);
+ ~optional();
+
+ operator bool_type() const;
+
+ optional& operator=(nullopt_t);
+
+ optional& operator=(const optional& other);
+ optional& operator=(optional&& other);
+
+ // The function does not participate in overload resolution unless std::is_same<std::decay_t<U>, T>::value is true
+ template <typename U>
+ // optional& operator=(U&& value);
+ optional& operator=(typename std::enable_if<std::is_same<typename std::decay<U>::type, T>::value, U>::type&& value);
+
+ T* operator->();
+ const T* operator->() const;
+ T& operator*();
+ const T& operator*() const;
+
+ T& value();
+ const T& value() const;
+
+# if defined(_MSC_VER) && (_MSC_VER > 1600)
+ template <typename U>
+ T value_or(U&& default_value) const &;
+
+ template <typename U>
+ T value_or(U&& default_value) &&;
+# else
+ T value_or(const T& default_value);
+ T value_or(const T& default_value) const;
+# endif
+
+ bool has_value() const;
+
+ void swap(optional& other);
+
+private:
+ T* value_ptr() { return reinterpret_cast< T*>(&_value); }
+ const T* value_ptr() const { return reinterpret_cast<const T*>(&_value); }
+
+ T& value_ref() { return *value_ptr(); }
+ const T& value_ref() const { return *value_ptr(); }
+
+ bool _has_value;
+ storage_type _value;
+# if defined(_DEBUG)
+ const T& _preview;
+# endif
+};
+
+
+//------------------------------------------------------------------------------
+template <typename T>
+inline optional<T>::optional():
+ _has_value(false)
+# if defined(_DEBUG)
+ ,_preview(value_ref())
+# endif
+{
+}
+
+template <typename T>
+inline optional<T>::optional(nullopt_t):
+ _has_value(false)
+# if defined(_DEBUG)
+ , _preview(value_ref())
+# endif
+{
+}
+
+template <typename T>
+inline optional<T>::optional(const optional& v):
+ _has_value(v._has_value)
+# if defined(_DEBUG)
+ , _preview(value_ref())
+# endif
+{
+ if (_has_value)
+ new (value_ptr()) T(v.value_ref());
+}
+
+template <typename T>
+inline optional<T>::optional(optional&& v):
+ _has_value(v._has_value)
+# if defined(_DEBUG)
+ , _preview(value_ref())
+# endif
+{
+ if (!_has_value)
+ return;
+
+ new (value_ptr()) T(std::move(v.value_ref()));
+ v.value_ref().~T();
+
+ v._has_value = false;
+}
+
+template <typename T>
+inline optional<T>::optional(const T& v):
+ _has_value(true)
+# if defined(_DEBUG)
+ , _preview(value_ref())
+# endif
+{
+ new (value_ptr()) T(v);
+}
+
+template <typename T>
+inline optional<T>::optional(T&& v):
+ _has_value(true)
+# if defined(_DEBUG)
+ , _preview(value_ref())
+# endif
+{
+ new (value_ptr()) T(std::forward<T>(v));
+}
+
+template <typename T>
+inline optional<T>::~optional()
+{
+ if (_has_value)
+ value_ref().~T();
+}
+
+template <typename T>
+inline optional<T>::operator bool_type() const
+{
+ return _has_value ? &optional::safe_bool : nullptr;
+}
+
+template <typename T>
+inline optional<T>& optional<T>::operator= (nullopt_t)
+{
+ optional().swap(*this);
+ _has_value = false;
+ return *this;
+}
+
+template <typename T>
+inline optional<T>& optional<T>::operator=(const optional& other)
+{
+ optional(other).swap(*this);
+ return *this;
+}
+
+template <typename T>
+inline optional<T>& optional<T>::operator=(optional&& other)
+{
+ optional(std::forward<optional>(other)).swap(*this);
+ return *this;
+}
+
+template <typename T>
+template <typename U>
+inline optional<T>& optional<T>::operator=(typename std::enable_if<std::is_same<typename std::decay<U>::type, T>::value, U>::type&& value)
+{
+ optional<T>(value).swap(*this);
+ return *this;
+}
+
+
+template <typename T>
+inline T* optional<T>::operator->()
+{
+ assert(_has_value);
+ return value_ptr();
+}
+
+template <typename T>
+inline const T* optional<T>::operator->() const
+{
+ assert(_has_value);
+ return value_ptr();
+}
+
+template <typename T>
+inline T& optional<T>::operator*()
+{
+ assert(_has_value);
+ return value_ref();
+}
+
+template <typename T>
+inline const T& optional<T>::operator*() const
+{
+ assert(_has_value);
+ return value_ref();
+}
+
+template <typename T>
+inline T& optional<T>::value()
+{
+ assert(_has_value);
+ return value_ref();
+}
+
+template <typename T>
+inline const T& optional<T>::value() const
+{
+ assert(_has_value);
+ return value_ref();
+}
+
+# if defined(_MSC_VER) && (_MSC_VER > 1600)
+template <typename T>
+template <typename U>
+inline T optional<T>::value_or(U&& default_value) const &
+{
+ return bool(*this) ? value_ref() : static_cast<T>(std::forward<U>(default_value));
+}
+
+template <typename T>
+template <typename U>
+inline T optional<T>::value_or(U&& default_value) &&
+{
+ return bool(*this) ? std::move(value_ref()) : static_cast<T>(std::forward<U>(default_value));
+}
+# else
+template <typename T>
+T optional<T>::value_or(const T& default_value)
+{
+ return _has_value ? value_ref() : default_value;
+}
+
+template <typename T>
+T optional<T>::value_or(const T& default_value) const
+{
+ return _has_value ? value_ref() : default_value;
+}
+# endif
+
+template <typename T>
+inline bool optional<T>::has_value() const
+{
+ return _has_value;
+}
+
+template <typename T>
+inline void optional<T>::swap(optional& other)
+{
+ using std::swap;
+
+ if (_has_value && other._has_value)
+ {
+ swap(value_ref(), other.value_ref());
+ }
+ else if (_has_value && !other._has_value)
+ {
+ new (other.value_ptr()) T(std::forward<T>(value_ref()));
+
+ value_ref().~T();
+
+ _has_value = false;
+ other._has_value = true;
+ }
+ else if (!_has_value && other._has_value)
+ {
+ new (value_ptr()) T(std::forward<T>(other.value_ref()));
+
+ other.value_ref().~T();
+
+ _has_value = true;
+ other._has_value = false;
+ }
+}
+
+
+//------------------------------------------------------------------------------
+template <typename T>
+optional<T> make_optional(T&& v)
+{
+ return optional<T>(std::forward<T>(v));
+}
+
+template <typename T>
+inline void swap(optional<T>& lhs, optional<T>& rhs)
+{
+ lhs.swap(rhs);
+}
+
+template <typename T>
+inline bool operator==(const optional<T>& lhs, const optional<T>& rhs)
+{
+ if (static_cast<bool>(lhs) != static_cast<bool>(rhs))
+ return false;
+ if (!static_cast<bool>(lhs))
+ return true;
+ return *lhs == *rhs;
+}
+
+template <typename T>
+bool operator!=(const optional<T>& lhs, const optional<T>& rhs)
+{
+ return !(lhs == rhs);
+}
+
+template <typename T>
+inline bool operator<(const optional<T>& lhs, const optional<T>& rhs)
+{
+ if (!static_cast<bool>(rhs))
+ return false;
+ if (!static_cast<bool>(lhs))
+ return true;
+ return *lhs < *rhs;
+}
+
+template <typename T>
+inline bool operator>(const optional<T>& lhs, const optional<T>& rhs)
+{
+ return rhs < lhs;
+}
+
+template <typename T>
+inline bool operator<=(const optional<T>& lhs, const optional<T>& rhs)
+{
+ return !(rhs < lhs);
+}
+
+template <typename T>
+inline bool operator>=(const optional<T>& lhs, const optional<T>& rhs)
+{
+ return !(lhs < rhs);
+}
+
+template <typename T>
+inline bool operator==(const optional<T>& opt, nullopt_t)
+{
+ return !static_cast<bool>(opt);
+}
+
+template <typename T>
+inline bool operator==(nullopt_t, const optional<T>& opt)
+{
+ return static_cast<bool>(opt);
+}
+
+template <typename T>
+inline bool operator!=(const optional<T>& opt, nullopt_t)
+{
+ return static_cast<bool>(opt);
+}
+
+template <typename T>
+inline bool operator!=(nullopt_t, const optional<T>& opt)
+{
+ return !static_cast<bool>(opt);
+}
+
+template <typename T>
+inline bool operator<(const optional<T>& opt, nullopt_t)
+{
+ return false;
+}
+
+template <typename T>
+inline bool operator<(nullopt_t, const optional<T>& opt)
+{
+ return static_cast<bool>(opt);
+}
+
+template <typename T>
+inline bool operator<=(const optional<T>& opt, nullopt_t)
+{
+ return !opt;
+}
+
+template <typename T>
+inline bool operator<=(nullopt_t, const optional<T>& opt)
+{
+ return true;
+}
+
+template <typename T>
+inline bool operator>(const optional<T>& opt, nullopt_t)
+{
+ return static_cast<bool>(opt);
+}
+
+template <typename T>
+inline bool operator>(nullopt_t, const optional<T>& opt)
+{
+ return false;
+}
+
+template <typename T>
+inline bool operator>=(const optional<T>&, nullopt_t)
+{
+ return true;
+}
+
+template <typename T>
+inline bool operator>=(nullopt_t, const optional<T>& opt)
+{
+ return !opt;
+}
+
+template <typename T>
+inline bool operator==(const optional<T>& opt, const T& v)
+{
+ return static_cast<bool>(opt) ? *opt == v : false;
+}
+
+template <typename T>
+inline bool operator==(const T& v, const optional<T>& opt)
+{
+ return static_cast<bool>(opt) ? *opt == v : false;
+}
+
+template <typename T>
+inline bool operator!=(const optional<T>& opt, const T& v)
+{
+ return static_cast<bool>(opt) ? *opt != v : true;
+}
+
+template <typename T>
+inline bool operator!=(const T& v, const optional<T>& opt)
+{
+ return static_cast<bool>(opt) ? *opt != v : true;
+}
+
+template <typename T>
+inline bool operator<(const optional<T>& opt, const T& v)
+{
+ using namespace std;
+ return static_cast<bool>(opt) ? less<T>(*opt, v) : true;
+}
+
+template <typename T>
+inline bool operator<(const T& v, const optional<T>& opt)
+{
+ using namespace std;
+ return static_cast<bool>(opt) ? less<T>(v, *opt) : false;
+}
+
+template <typename T>
+inline bool operator<=(const optional<T>& opt, const T& v)
+{
+ using namespace std;
+ return static_cast<bool>(opt) ? less_equal<T>(*opt, v) : true;
+}
+
+template <typename T>
+inline bool operator<=(const T& v, const optional<T>& opt)
+{
+ using namespace std;
+ return static_cast<bool>(opt) ? less_equal<T>(v, *opt) : false;
+}
+
+template <typename T>
+inline bool operator>(const optional<T>& opt, const T& v)
+{
+ using namespace std;
+ return static_cast<bool>(opt) ? greater<T>(*opt, v) : false;
+}
+
+template <typename T>
+inline bool operator>(const T& v, const optional<T>& opt)
+{
+ using namespace std;
+ return static_cast<bool>(opt) ? greater<T>(v, *opt) : true;
+}
+
+template <typename T>
+inline bool operator>=(const optional<T>& opt, const T& v)
+{
+ using namespace std;
+ return static_cast<bool>(opt) ? greater_equal<T>(*opt, v) : false;
+}
+
+template <typename T>
+inline bool operator>=(const T& v, const optional<T>& opt)
+{
+ using namespace std;
+ return static_cast<bool>(opt) ? greater_equal<T>(v, *opt) : true;
+}
+
+
+# endif // __TD__OPTIONAL_H__