aboutsummaryrefslogtreecommitdiff
path: root/libbutl/optional.mxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-09-22 23:32:28 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-09-22 23:32:28 +0200
commitc09cd7512491cee1e82c1ad8128ce9fd4bc3f79b (patch)
treea659ed768d849130ab5780a11b7f791a463a1a91 /libbutl/optional.mxx
parent2a00871f07067f8f9e2de08bb9c8f50e1bf6a650 (diff)
Initial modularization with both Clang and VC hacks
Note: gave up on VC about half way though.
Diffstat (limited to 'libbutl/optional.mxx')
-rw-r--r--libbutl/optional.mxx113
1 files changed, 113 insertions, 0 deletions
diff --git a/libbutl/optional.mxx b/libbutl/optional.mxx
new file mode 100644
index 0000000..4478f84
--- /dev/null
+++ b/libbutl/optional.mxx
@@ -0,0 +1,113 @@
+// file : libbutl/optional.mxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef __cpp_modules
+#pragma once
+#endif
+
+// C includes.
+
+#ifndef __cpp_lib_modules
+#include <utility> // move()
+#include <functional> // hash
+#endif
+
+// Other includes.
+
+#ifdef __cpp_modules
+export module butl.optional;
+#ifdef __cpp_lib_modules
+import std.core;
+#endif
+#endif
+
+#include <libbutl/export.hxx>
+
+LIBBUTL_MODEXPORT namespace butl
+{
+ // Simple optional class template while waiting for std::optional.
+ //
+ struct nullopt_t {constexpr explicit nullopt_t (int) {}};
+#if defined(__cpp_modules) && defined(__clang__) //@@ MOD Clang duplicate sym.
+ inline
+#endif
+ const/*expr*/ nullopt_t nullopt (1); //@@ MOD VC multiple defs.
+
+ 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);
+ }
+ };
+}