aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2020-05-19 21:19:58 +0300
committerBoris Kolpackov <boris@codesynthesis.com>2020-06-26 16:33:27 +0200
commit82b9af71dd5aa3ad6fee808e91e9b1024ebaeafb (patch)
treeaa37c5235b00d5126a3f841b82247b419dc5c46a
parentaf85a3694788ca5c9e5a9e6f525e4934ed5eb64c (diff)
Improve std::optional to better deal with lack of copy/move constructors
-rw-r--r--libbutl/optional.mxx83
-rw-r--r--tests/optional/buildfile6
-rw-r--r--tests/optional/driver.cxx43
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));
+}