From 82b9af71dd5aa3ad6fee808e91e9b1024ebaeafb Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 19 May 2020 21:19:58 +0300 Subject: Improve std::optional to better deal with lack of copy/move constructors --- libbutl/optional.mxx | 83 +++++++++++++++++++++++++++++++++++++++++++---- tests/optional/buildfile | 6 ++++ tests/optional/driver.cxx | 43 ++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 tests/optional/buildfile create mode 100644 tests/optional/driver.cxx 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 // move() # include // hash -# include // is_trivially_destructible +# include // 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 ::value, + bool = std::is_move_constructible::value> + struct optional_ctors: optional_data + { + using optional_data::optional_data; + }; + + template + struct optional_ctors: optional_ctors + { + using optional_ctors::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 + struct optional_ctors: optional_ctors + { + using optional_ctors::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 + struct optional_ctors: optional_ctors + { + using optional_ctors::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 - class optional: private details::optional_data + class optional: private details::optional_ctors { - using base = details::optional_data; + using base = details::optional_ctors; 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 + +#ifndef __cpp_lib_modules_ts +#include +#include // move() +#endif + +// Other includes. + +#ifdef __cpp_modules_ts +#ifdef __cpp_lib_modules_ts +import std.core; +#endif +import butl.optional; +#else +#include +#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 r; + vector> rs; + rs.emplace_back (move (r)); +} -- cgit v1.1