diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2017-09-22 23:32:28 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2017-09-22 23:32:28 +0200 |
commit | c09cd7512491cee1e82c1ad8128ce9fd4bc3f79b (patch) | |
tree | a659ed768d849130ab5780a11b7f791a463a1a91 /libbutl/optional.mxx | |
parent | 2a00871f07067f8f9e2de08bb9c8f50e1bf6a650 (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.mxx | 113 |
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); + } + }; +} |