From 88c0ed30da6937146ffdcbc880053ba6ceacebbb Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Mon, 29 Sep 2014 18:56:08 +0000 Subject: [PATCH] Add getValueOr to llvm::Optional. This takes a single argument convertible to T, and - if the Optional has a value, returns the existing value, - otherwise, constructs a T from the argument and returns that. Inspired by std::experimental::optional from the "Library Fundamentals" C++ TS. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218618 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/Optional.h | 10 ++++++++++ unittests/ADT/OptionalTest.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index cb45c78e2c1..144367d352d 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -119,9 +119,19 @@ public: const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } + template + constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION { + return hasValue() ? getValue() : std::forward(value); + } + #if LLVM_HAS_RVALUE_REFERENCE_THIS T&& getValue() && { assert(hasVal); return std::move(*getPointer()); } T&& operator*() && { assert(hasVal); return std::move(*getPointer()); } + + template + T getValueOr(U &&value) && { + return hasValue() ? std::move(getValue()) : std::forward(value); + } #endif }; diff --git a/unittests/ADT/OptionalTest.cpp b/unittests/ADT/OptionalTest.cpp index 2da408c15e0..51c54523b88 100644 --- a/unittests/ADT/OptionalTest.cpp +++ b/unittests/ADT/OptionalTest.cpp @@ -169,6 +169,14 @@ TEST_F(OptionalTest, NullCopyConstructionTest) { EXPECT_EQ(0u, NonDefaultConstructible::Destructions); } +TEST_F(OptionalTest, GetValueOr) { + Optional A; + EXPECT_EQ(42, A.getValueOr(42)); + + A = 5; + EXPECT_EQ(5, A.getValueOr(42)); +} + struct MoveOnly { static unsigned MoveConstructions; static unsigned Destructions; @@ -278,5 +286,26 @@ TEST_F(OptionalTest, MoveOnlyAssigningAssignment) { EXPECT_EQ(1u, MoveOnly::Destructions); } +#if LLVM_HAS_RVALUE_REFERENCE_THIS + +TEST_F(OptionalTest, MoveGetValueOr) { + Optional A; + + MoveOnly::ResetCounts(); + EXPECT_EQ(42, std::move(A).getValueOr(MoveOnly(42)).val); + EXPECT_EQ(1u, MoveOnly::MoveConstructions); + EXPECT_EQ(0u, MoveOnly::MoveAssignments); + EXPECT_EQ(2u, MoveOnly::Destructions); + + A = MoveOnly(5); + MoveOnly::ResetCounts(); + EXPECT_EQ(5, std::move(A).getValueOr(MoveOnly(42)).val); + EXPECT_EQ(1u, MoveOnly::MoveConstructions); + EXPECT_EQ(0u, MoveOnly::MoveAssignments); + EXPECT_EQ(2u, MoveOnly::Destructions); +} + +#endif // LLVM_HAS_RVALUE_REFERENCE_THIS + } // end anonymous namespace -- 2.34.1