diff options
Diffstat (limited to 'libbutl/optional.hxx')
-rw-r--r-- | libbutl/optional.hxx | 164 |
1 files changed, 155 insertions, 9 deletions
diff --git a/libbutl/optional.hxx b/libbutl/optional.hxx index 28aa95a..f22189b 100644 --- a/libbutl/optional.hxx +++ b/libbutl/optional.hxx @@ -63,9 +63,7 @@ #ifdef LIBBUTL_STD_OPTIONAL namespace butl { - template <typename T> - using optional = std::optional<T>; - + using std::optional; using std::nullopt_t; using std::nullopt; } @@ -110,10 +108,16 @@ namespace butl #if (!defined(_MSC_VER) || _MSC_VER > 1900) && \ (!defined(__GNUC__) || __GNUC__ > 4 || defined(__clang__)) constexpr optional_data (const optional_data& o): v_ (o.v_) {if (v_) new (&d_) T (o.d_);} - constexpr optional_data (optional_data&& o): v_ (o.v_) {if (v_) new (&d_) T (std::move (o.d_));} + + constexpr optional_data (optional_data&& o) + noexcept (std::is_nothrow_move_constructible<T>::value) + : v_ (o.v_) {if (v_) new (&d_) T (std::move (o.d_));} #else optional_data (const optional_data& o): v_ (o.v_) {if (v_) new (&d_) T (o.d_);} - optional_data (optional_data&& o): v_ (o.v_) {if (v_) new (&d_) T (std::move (o.d_));} + + optional_data (optional_data&& o) + noexcept (std::is_nothrow_move_constructible<T>::value) + : v_ (o.v_) {if (v_) new (&d_) T (std::move (o.d_));} #endif optional_data& operator= (nullopt_t); @@ -121,7 +125,11 @@ namespace butl optional_data& operator= (T&&); optional_data& operator= (const optional_data&); - optional_data& operator= (optional_data&&); + + optional_data& operator= (optional_data&&) + noexcept (std::is_nothrow_move_constructible<T>::value && + std::is_nothrow_move_assignable<T>::value && + std::is_nothrow_destructible<T>::value); ~optional_data (); }; @@ -153,10 +161,16 @@ namespace butl #if (!defined(_MSC_VER) || _MSC_VER > 1900) && \ (!defined(__GNUC__) || __GNUC__ > 4 || defined(__clang__)) constexpr optional_data (const optional_data& o): v_ (o.v_) {if (v_) new (&d_) T (o.d_);} - constexpr optional_data (optional_data&& o): v_ (o.v_) {if (v_) new (&d_) T (std::move (o.d_));} + + constexpr optional_data (optional_data&& o) + noexcept (std::is_nothrow_move_constructible<T>::value) + : v_ (o.v_) {if (v_) new (&d_) T (std::move (o.d_));} #else optional_data (const optional_data& o): v_ (o.v_) {if (v_) new (&d_) T (o.d_);} - optional_data (optional_data&& o): v_ (o.v_) {if (v_) new (&d_) T (std::move (o.d_));} + + optional_data (optional_data&& o) + noexcept (std::is_nothrow_move_constructible<T>::value) + : v_ (o.v_) {if (v_) new (&d_) T (std::move (o.d_));} #endif optional_data& operator= (nullopt_t); @@ -164,7 +178,12 @@ namespace butl optional_data& operator= (T&&); optional_data& operator= (const optional_data&); - optional_data& operator= (optional_data&&); + + // Note: it is trivially destructible and thus is no-throw destructible. + // + optional_data& operator= (optional_data&&) + noexcept (std::is_nothrow_move_constructible<T>::value && + std::is_nothrow_move_assignable<T>::value); }; template <typename T, @@ -291,6 +310,8 @@ namespace butl explicit operator bool () const {return this->v_;} }; + // optional ? optional + // template <typename T> inline auto operator== (const optional<T>& x, const optional<T>& y) @@ -320,6 +341,131 @@ namespace butl { return y < x; } + + // optional ? nullopt + // nullopt ? optional + // + template <typename T> + inline auto + operator== (const optional<T>& x, nullopt_t) + { + bool px (x); + return !px; + } + + template <typename T> + inline auto + operator== (nullopt_t, const optional<T>& y) + { + bool py (y); + return !py; + } + + template <typename T> + inline auto + operator!= (const optional<T>& x, nullopt_t y) + { + return !(x == y); + } + + template <typename T> + inline auto + operator!= (nullopt_t x, const optional<T>& y) + { + return !(x == y); + } + + template <typename T> + inline auto + operator< (const optional<T>&, nullopt_t) + { + return false; + } + + template <typename T> + inline auto + operator< (nullopt_t, const optional<T>& y) + { + bool py (y); + return py; + } + + template <typename T> + inline auto + operator> (const optional<T>& x, nullopt_t y) + { + return y < x; + } + + template <typename T> + inline auto + operator> (nullopt_t x, const optional<T>& y) + { + return y < x; + } + + // optional ? T + // T ? optional + // + template <typename T> + inline auto + operator== (const optional<T>& x, const T& y) + { + bool px (x); + return px && *x == y; + } + + template <typename T> + inline auto + operator== (const T& x, const optional<T>& y) + { + bool py (y); + return py && x == *y; + } + + template <typename T> + inline auto + operator!= (const optional<T>& x, const T& y) + { + return !(x == y); + } + + template <typename T> + inline auto + operator!= (const T& x, const optional<T>& y) + { + return !(x == y); + } + + template <typename T> + inline auto + operator< (const optional<T>& x, const T& y) + { + bool px (x); + return !px || *x < y; + } + + template <typename T> + inline auto + operator< (const T& x, const optional<T>& y) + { + bool py (y); + return py && x < *y; + } + + template <typename T> + inline auto + operator> (const optional<T>& x, const T& y) + { + return y < x; + } + + template <typename T> + inline auto + operator> (const T& x, const optional<T>& y) + { + return y < x; + } } namespace std |