aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-06-26 15:29:41 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-06-26 15:29:51 +0200
commit874026e26b56d10b0bb9540180b564b36e685a17 (patch)
treeaa37c5235b00d5126a3f841b82247b419dc5c46a
parenteac178a2dea0857d91838b54844e74285b5957c6 (diff)
-rw-r--r--libbutl/optional.mxx83
-rw-r--r--tests/optional/driver.cxx16
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));
}