[PATCH] D85072: [ADT] Add getAsOr to Optional

Nathan James via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 3 02:58:56 PDT 2020


njames93 updated this revision to Diff 282558.
njames93 added a comment.

Delete the rvalue reference version as it can create dangling references


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D85072/new/

https://reviews.llvm.org/D85072

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
@@ -7,13 +7,14 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/raw_ostream.h"
 #include "gtest/gtest-spi.h"
 #include "gtest/gtest.h"
 
 #include <array>
-
+#include <initializer_list>
 
 using namespace llvm;
 
@@ -193,6 +194,32 @@
   EXPECT_EQ(5, A.getValueOr(42));
 }
 
+TEST_F(OptionalTest, GetAsOr) {
+  Optional<std::string> String;
+  StringRef Default{"DefaultOverflowSmallStringOpt"};
+  StringRef Value{"Value"};
+  EXPECT_EQ(Default, String.getAsOr(Default));
+  String.emplace(Value);
+  EXPECT_EQ(Value, String.getAsOr(Default));
+
+  int Item = 0;
+  ArrayRef<int> OneItem = makeArrayRef(Item);
+  ArrayRef<int> Empty;
+
+  Optional<llvm::SmallVector<int, 4>> SmallVec;
+  EXPECT_EQ(SmallVec.getAsOr(Empty).size(), 0U);
+  EXPECT_EQ(SmallVec.getAsOr(ArrayRef<int>{}).size(), 0U);
+  EXPECT_EQ(SmallVec.getAsOr(OneItem).size(), 1U);
+  SmallVec.emplace(std::initializer_list<int>{0, 1, 2, 3});
+  EXPECT_EQ(SmallVec.getAsOr(Empty).size(), 4U);
+
+  Optional<std::vector<int>> Vector;
+  EXPECT_EQ(Vector.getAsOr(Empty).size(), 0U);
+  EXPECT_EQ(Vector.getAsOr(OneItem).size(), 1U);
+  Vector.emplace(std::initializer_list<int>{0, 1, 2, 3});
+  EXPECT_EQ(Vector.getAsOr(Empty).size(), 4U);
+}
+
 struct MultiArgConstructor {
   int x, y;
   MultiArgConstructor(int x, int y) : x(x), y(y) {}
Index: llvm/include/llvm/ADT/Optional.h
===================================================================
--- llvm/include/llvm/ADT/Optional.h
+++ llvm/include/llvm/ADT/Optional.h
@@ -267,6 +267,14 @@
     return hasValue() ? getValue() : std::forward<U>(value);
   }
 
+  /// Returns the value contained in this as a ``U`` if present, otherwise
+  /// return \p Default.
+  template <typename U> U getAsOr(U Default) const LLVM_LVALUE_FUNCTION {
+    if (hasValue())
+      return static_cast<U>(getValue());
+    return Default;
+  }
+
   /// Apply a function to the value if present; otherwise return None.
   template <class Function>
   auto map(const Function &F) const LLVM_LVALUE_FUNCTION
@@ -284,6 +292,10 @@
     return hasValue() ? std::move(getValue()) : std::forward<U>(value);
   }
 
+  // Delete this as it can lead to dangling reference issues if ``U`` references
+  // the value held in the Optional.
+  template <typename U> U getAsOr(U Default) && = delete;
+
   /// Apply a function to the value if present; otherwise return None.
   template <class Function>
   auto map(const Function &F) &&


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D85072.282558.patch
Type: text/x-patch
Size: 2772 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200803/4a61f08b/attachment.bin>


More information about the llvm-commits mailing list