diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2020-05-19 21:19:58 +0300 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2020-06-26 16:33:27 +0200 |
commit | 82b9af71dd5aa3ad6fee808e91e9b1024ebaeafb (patch) | |
tree | aa37c5235b00d5126a3f841b82247b419dc5c46a | |
parent | af85a3694788ca5c9e5a9e6f525e4934ed5eb64c (diff) |
Improve std::optional to better deal with lack of copy/move constructors
-rw-r--r-- | libbutl/optional.mxx | 83 | ||||
-rw-r--r-- | tests/optional/buildfile | 6 | ||||
-rw-r--r-- | tests/optional/driver.cxx | 43 |
3 files changed, 126 insertions, 6 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/buildfile b/tests/optional/buildfile new file mode 100644 index 0000000..68188d7 --- /dev/null +++ b/tests/optional/buildfile @@ -0,0 +1,6 @@ +# file : tests/optional/buildfile +# license : MIT; see accompanying LICENSE file + +import libs = libbutl%lib{butl} + +exe{driver}: {hxx cxx}{*} $libs diff --git a/tests/optional/driver.cxx b/tests/optional/driver.cxx new file mode 100644 index 0000000..5d72f08 --- /dev/null +++ b/tests/optional/driver.cxx @@ -0,0 +1,43 @@ +// file : tests/optional/driver.cxx -*- C++ -*- +// license : MIT; see accompanying LICENSE file + +#include <cassert> + +#ifndef __cpp_lib_modules_ts +#include <vector> +#include <utility> // move() +#endif + +// Other includes. + +#ifdef __cpp_modules_ts +#ifdef __cpp_lib_modules_ts +import std.core; +#endif +import butl.optional; +#else +#include <libbutl/optional.mxx> +#endif + +using namespace std; + +struct move_only +{ + move_only () = default; + + move_only (move_only&&) = default; + move_only& operator= (move_only&&) = default; + + move_only (const move_only&) = delete; + move_only& operator= (const move_only&) = delete; +}; + +int +main () +{ + using butl::optional; + + optional<move_only> r; + vector<optional<move_only>> rs; + rs.emplace_back (move (r)); +} |