diff options
-rw-r--r-- | libbutl/optional.mxx | 83 | ||||
-rw-r--r-- | tests/optional/driver.cxx | 16 |
2 files changed, 85 insertions, 14 deletions
diff --git a/libbutl/optional.mxx b/libbutl/optional.mxx index fe533c5..d32e14b 100644 --- a/libbutl/optional.mxx +++ b/libbutl/optional.mxx @@ -60,7 +60,7 @@ #else # include <utility> // move() # include <functional> // hash -# include <type_traits> // is_trivially_destructible +# include <type_traits> // is_* #endif #endif @@ -91,9 +91,6 @@ 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_ts) && defined(__clang__) //@@ MOD Clang duplicate sym. - inline -#endif constexpr nullopt_t nullopt (1); namespace details @@ -184,12 +181,86 @@ LIBBUTL_MODEXPORT namespace butl optional_data& operator= (const optional_data&); optional_data& operator= (optional_data&&); }; + + template <typename T, + bool = std::is_copy_constructible<T>::value, + bool = std::is_move_constructible<T>::value> + struct optional_ctors: optional_data<T> + { + using optional_data<T>::optional_data; + }; + + template <typename T> + struct optional_ctors<T, false, true>: optional_ctors<T, true, true> + { + using optional_ctors<T, true, true>::optional_ctors; + +#if !defined(_MSC_VER) || _MSC_VER > 1900 + constexpr optional_ctors () = default; +#else + optional_ctors () = default; +#endif + + optional_ctors (const optional_ctors&) = delete; + +#if (!defined(_MSC_VER) || _MSC_VER > 1900) && \ + (!defined(__GNUC__) || __GNUC__ > 4 || defined(__clang__)) + constexpr optional_ctors (optional_ctors&&) = default; +#else + optional_ctors (optional_ctors&&) = default; +#endif + + optional_ctors& operator= (const optional_ctors&) = default; + optional_ctors& operator= (optional_ctors&&) = default; + }; + + template <typename T> + struct optional_ctors<T, true, false>: optional_ctors<T, true, true> + { + using optional_ctors<T, true, true>::optional_ctors; + +#if !defined(_MSC_VER) || _MSC_VER > 1900 + constexpr optional_ctors () = default; +#else + optional_ctors () = default; +#endif + +#if (!defined(_MSC_VER) || _MSC_VER > 1900) && \ + (!defined(__GNUC__) || __GNUC__ > 4 || defined(__clang__)) + constexpr optional_ctors (const optional_ctors&) = default; +#else + optional_ctors (const optional_ctors&) = default; +#endif + + optional_ctors (optional_ctors&&) = delete; + + optional_ctors& operator= (const optional_ctors&) = default; + optional_ctors& operator= (optional_ctors&&) = default; + }; + + template <typename T> + struct optional_ctors<T, false, false>: optional_ctors<T, true, true> + { + using optional_ctors<T, true, true>::optional_ctors; + +#if !defined(_MSC_VER) || _MSC_VER > 1900 + constexpr optional_ctors () = default; +#else + optional_ctors () = default; +#endif + + optional_ctors (const optional_ctors&) = delete; + optional_ctors (optional_ctors&&) = delete; + + optional_ctors& operator= (const optional_ctors&) = default; + optional_ctors& operator= (optional_ctors&&) = default; + }; } template <typename T> - class optional: private details::optional_data<T> + class optional: private details::optional_ctors<T> { - using base = details::optional_data<T>; + using base = details::optional_ctors<T>; public: using value_type = T; diff --git a/tests/optional/driver.cxx b/tests/optional/driver.cxx index e63c985..5d72f08 100644 --- a/tests/optional/driver.cxx +++ b/tests/optional/driver.cxx @@ -21,15 +21,15 @@ import butl.optional; using namespace std; -struct redirect +struct move_only { - redirect () = default; + move_only () = default; - redirect (redirect&&) = default; - redirect& operator= (redirect&&) = default; + move_only (move_only&&) = default; + move_only& operator= (move_only&&) = default; - redirect (const redirect&) = delete; - redirect& operator= (const redirect&) = delete; + move_only (const move_only&) = delete; + move_only& operator= (const move_only&) = delete; }; int @@ -37,7 +37,7 @@ main () { using butl::optional; - optional<redirect> r; - vector<optional<redirect>> rs; + optional<move_only> r; + vector<optional<move_only>> rs; rs.emplace_back (move (r)); } |