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