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

Nathan James via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 1 03:23:48 PDT 2020


njames93 created this revision.
njames93 added reviewers: chandlerc, dblaikie, bkramer.
Herald added subscribers: llvm-commits, dexonsmith.
Herald added a project: LLVM.
njames93 requested review of this revision.

Adds a method `getAsOr` to `Optional`, This functions somewhat like `getValueOr` however it casts the value to a different type.
This is particularily useful if the type contained in the optional is expensive to construct.

Typical use cases would be for `Optional<std::string>`, It would often only be needed to access the value as a `StringRef`.
Similar approach can be made for `ArrayRef`.

This function is enabled for any type that can be statically casted from the type contained in the `Optional`


Repository:
  rG LLVM Github Monorepo

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>
+  constexpr std::enable_if_t<std::is_convertible<T, U>::value, U>
+  getAsOr(U Default) const {
+    return hasValue() ? static_cast<U>(getValue()) : std::forward<U>(Default);
+  }
+
   /// Apply a function to the value if present; otherwise return None.
   template <class Function>
   auto map(const Function &F) const LLVM_LVALUE_FUNCTION


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D85072.282385.patch
Type: text/x-patch
Size: 2398 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200801/526367d6/attachment.bin>


More information about the llvm-commits mailing list