aboutsummaryrefslogtreecommitdiff
path: root/libbutl/optional.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbutl/optional.hxx')
-rw-r--r--libbutl/optional.hxx164
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