Nullable.h (2887B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_Nullable_h 8 #define mozilla_dom_Nullable_h 9 10 #include <ostream> 11 #include <utility> 12 13 #include "mozilla/Maybe.h" 14 #include "nsTArrayForwardDeclare.h" 15 16 class nsCycleCollectionTraversalCallback; 17 18 namespace mozilla::dom { 19 20 // Support for nullable types 21 template <typename T> 22 struct Nullable { 23 private: 24 Maybe<T> mValue; 25 26 public: 27 Nullable() : mValue() {} 28 29 MOZ_IMPLICIT Nullable(const decltype(nullptr)&) : mValue() {} 30 31 explicit Nullable(const T& aValue) : mValue() { mValue.emplace(aValue); } 32 33 MOZ_IMPLICIT Nullable(T&& aValue) : mValue() { 34 mValue.emplace(std::move(aValue)); 35 } 36 37 Nullable(Nullable<T>&& aOther) : mValue(std::move(aOther.mValue)) {} 38 39 Nullable(const Nullable<T>& aOther) : mValue(aOther.mValue) {} 40 41 void operator=(const Nullable<T>& aOther) { mValue = aOther.mValue; } 42 43 void SetValue(const T& aArgs) { 44 mValue.reset(); 45 mValue.emplace(aArgs); 46 } 47 48 void SetValue(T&& aArgs) { 49 mValue.reset(); 50 mValue.emplace(std::move(aArgs)); 51 } 52 53 // For cases when |T| is some type with nontrivial copy behavior, we may want 54 // to get a reference to our internal copy of T and work with it directly 55 // instead of relying on the copying version of SetValue(). 56 T& SetValue() { 57 if (mValue.isNothing()) { 58 mValue.emplace(); 59 } 60 return mValue.ref(); 61 } 62 63 void SetNull() { mValue.reset(); } 64 65 const T& Value() const { return mValue.ref(); } 66 67 T& Value() { return mValue.ref(); } 68 69 bool IsNull() const { return mValue.isNothing(); } 70 71 bool Equals(const Nullable<T>& aOtherNullable) const { 72 return mValue == aOtherNullable.mValue; 73 } 74 75 bool operator==(const Nullable<T>& aOtherNullable) const { 76 return Equals(aOtherNullable); 77 } 78 79 bool operator!=(const Nullable<T>& aOtherNullable) const { 80 return !Equals(aOtherNullable); 81 } 82 83 friend std::ostream& operator<<(std::ostream& aStream, 84 const Nullable& aNullable) { 85 return aStream << aNullable.mValue; 86 } 87 }; 88 89 template <typename T> 90 void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, 91 Nullable<T>& aNullable, const char* aName, 92 uint32_t aFlags = 0) { 93 if (!aNullable.IsNull()) { 94 ImplCycleCollectionTraverse(aCallback, aNullable.Value(), aName, aFlags); 95 } 96 } 97 98 template <typename T> 99 void ImplCycleCollectionUnlink(Nullable<T>& aNullable) { 100 if (!aNullable.IsNull()) { 101 ImplCycleCollectionUnlink(aNullable.Value()); 102 } 103 } 104 105 } // namespace mozilla::dom 106 107 #endif /* mozilla_dom_Nullable_h */