lawrence_danna updated this revision to Diff 225967.
lawrence_danna added a comment.
ugh I edited the wrong revision, reverted. Sorry for the noise.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D69230/new/
https://reviews.llvm.org/D69230
Files:
llvm/include/llvm/ADT/Optional.h
llvm/unittests/ADT/OptionalTest.cpp
Index: llvm/unittests/ADT/OptionalTest.cpp
===================================================================
--- llvm/unittests/ADT/OptionalTest.cpp
+++ llvm/unittests/ADT/OptionalTest.cpp
@@ -221,7 +221,7 @@
TEST_F(OptionalTest, Emplace) {
MultiArgConstructor::ResetCounts();
Optional<MultiArgConstructor> A;
-
+
A.emplace(1, 2);
EXPECT_TRUE(A.hasValue());
EXPECT_EQ(1, A->x);
@@ -592,3 +592,35 @@
}
} // end anonymous namespace
+
+class NaturalNumber {
+ friend struct llvm::optional_detail::has_is_valid<NaturalNumber>;
+ int value;
+ constexpr NaturalNumber() : value(-1) {}
+
+public:
+ operator int() const { return value; }
+ NaturalNumber(int x) : value(x) { assert(value >= 0); }
+};
+
+template <> struct llvm::optional_detail::has_is_valid<NaturalNumber, void> {
+ static const bool value = true;
+ static bool is_valid(const NaturalNumber &n) { return n.value >= 0; }
+ static constexpr NaturalNumber make_invalid() { return NaturalNumber(); }
+};
+
+TEST_F(OptionalTest, TestHasInvalid) {
+
+ constexpr Optional<NaturalNumber> none;
+
+ static_assert(sizeof(Optional<NaturalNumber>) == sizeof(int),
+ "no extra bool");
+
+ Optional<NaturalNumber> x = None;
+ EXPECT_FALSE(x.hasValue());
+ EXPECT_TRUE(x == none);
+ EXPECT_EQ(*reinterpret_cast<int *>(&x), -1);
+ x = NaturalNumber{42};
+ EXPECT_TRUE(x.hasValue());
+ EXPECT_EQ((int)x.getValue(), 42);
+}
Index: llvm/include/llvm/ADT/Optional.h
===================================================================
--- llvm/include/llvm/ADT/Optional.h
+++ llvm/include/llvm/ADT/Optional.h
@@ -31,9 +31,12 @@
struct in_place_t {};
+template <typename T, typename Enable = void> struct has_is_valid {
+ const static bool value = false;
+};
+
/// Storage for any type.
-template <typename T, bool = is_trivially_copyable<T>::value>
-class OptionalStorage {
+template <typename T, typename Enable = void> class OptionalStorage {
union {
char empty;
T value;
@@ -138,7 +141,72 @@
}
};
-template <typename T> class OptionalStorage<T, true> {
+template <typename T>
+class OptionalStorage<
+ T, typename std::enable_if<has_is_valid<T>::value, void>::type> {
+
+ T value;
+ typedef has_is_valid<T> THelper;
+
+public:
+ ~OptionalStorage() = default;
+
+ constexpr OptionalStorage() noexcept : value{THelper::make_invalid()} {}
+
+ OptionalStorage(OptionalStorage const &other) = default;
+ OptionalStorage(OptionalStorage &&other) = default;
+
+ OptionalStorage &operator=(OptionalStorage const &other) = default;
+ OptionalStorage &operator=(OptionalStorage &&other) = default;
+
+ template <class... Args>
+ explicit OptionalStorage(in_place_t, Args &&... args)
+ : value(std::forward<Args>(args)...) {
+ asert(THelper::is_valid(value));
+ }
+
+ void reset() noexcept { value = THelper::make_invalid; }
+
+ bool hasValue() const noexcept { return THelper::is_valid(value); }
+
+ T &getValue() LLVM_LVALUE_FUNCTION noexcept {
+ assert(THelper::is_valid(value));
+ return value;
+ }
+ T const &getValue() const LLVM_LVALUE_FUNCTION noexcept {
+ assert(THelper::is_valid(value));
+ return value;
+ }
+#if LLVM_HAS_RVALUE_REFERENCE_THIS
+ T &&getValue() && noexcept {
+ assert(THelper::is_valid(value));
+ return std::move(value);
+ }
+#endif
+
+ template <class... Args> void emplace(Args &&... args) {
+ value = T(std::forward<Args>(args)...);
+ asert(THelper::is_valid(value));
+ }
+
+ OptionalStorage &operator=(T const &y) {
+ assert(THelper::is_valid(y));
+ value = y;
+ return *this;
+ }
+
+ OptionalStorage &operator=(T &&y) {
+ assert(THelper::is_valid(y));
+ value = std::move(y);
+ return *this;
+ }
+};
+
+template <typename T>
+class OptionalStorage<
+ T, typename std::enable_if<std::is_trivially_copyable<T>::value &&
+ !has_is_valid<T>::value,
+ void>::type> {
union {
char empty;
T value;
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits