diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2017-05-01 16:08:43 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2017-05-01 16:59:24 +0300 |
commit | 61377c582e0f2675baa5f5e6e30a35d1a4164b33 (patch) | |
tree | 11cdca992834d7f7f197f72856712fbcb3020e3d /libbutl/optional.hxx | |
parent | 442c1a6790e52baa0c081f310d4d9e9b6f1ff638 (diff) |
Add hxx extension for headers and lib prefix for library dir
Diffstat (limited to 'libbutl/optional.hxx')
-rw-r--r-- | libbutl/optional.hxx | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/libbutl/optional.hxx b/libbutl/optional.hxx new file mode 100644 index 0000000..c1bc582 --- /dev/null +++ b/libbutl/optional.hxx @@ -0,0 +1,96 @@ +// file : libbutl/optional.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef LIBBUTL_OPTIONAL_HXX +#define LIBBUTL_OPTIONAL_HXX + +#include <utility> // move() +#include <functional> // hash + +namespace butl +{ + // Simple optional class template while waiting for std::optional. + // + struct nullopt_t {constexpr explicit nullopt_t (int) {}}; + constexpr const nullopt_t nullopt (1); + + template <typename T> + class optional + { + public: + typedef T value_type; + + constexpr optional (): value_ (), null_ (true) {} // VC14 needs value_(). + constexpr optional (nullopt_t): value_ (), null_ (true) {} + constexpr optional (const T& v): value_ (v), null_ (false) {} + constexpr optional (T&& v): value_ (std::move (v)), null_ (false) {} + + optional& operator= (nullopt_t) {value_ = T (); null_ = true; return *this;} + optional& operator= (const T& v) {value_ = v; null_ = false; return *this;} + optional& operator= (T&& v) {value_ = std::move (v); null_ = false; return *this;} + + T& value () {return value_;} + const T& value () const {return value_;} + + T* operator-> () {return &value_;} + const T* operator-> () const {return &value_;} + + T& operator* () {return value_;} + const T& operator* () const {return value_;} + + bool has_value () const {return !null_;} + explicit operator bool () const {return !null_;} + + private: + T value_; + bool null_; + }; + + template <typename T> + inline auto + operator== (const optional<T>& x, const optional<T>& y) -> decltype (*x == *y) + { + return static_cast<bool> (x) == static_cast<bool> (y) && (!x || *x == *y); + } + + template <typename T> + inline auto + operator!= (const optional<T>& x, const optional<T>& y) -> decltype (x == y) + { + return !(x == y); + } + + template <typename T> + inline auto + operator< (const optional<T>& x, const optional<T>& y) -> decltype (*x < *y) + { + bool px (x), py (y); + return px < py || (px && py && *x < *y); + } + + template <typename T> + inline auto + operator> (const optional<T>& x, const optional<T>& y) -> decltype (*x > *y) + { + return y < x; + } +} + +namespace std +{ + template <typename T> + struct hash<butl::optional<T>>: hash<T> + { + using argument_type = butl::optional<T>; + + size_t + operator() (const butl::optional<T>& o) const + noexcept (noexcept (hash<T> {} (*o))) + { + return o ? hash<T>::operator() (*o) : static_cast<size_t> (-3333); + } + }; +} + +#endif // LIBBUTL_OPTIONAL_HXX |