mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-30 04:17:31 +09:00
Issue #2255 - Add support for Maybe<T&> https://bugzilla.mozilla.org/show_bug.cgi?id=1620568 Make Maybe<T>::emplace() work when T is const https://bugzilla.mozilla.org/show_bug.cgi?id=1335780
This commit is contained in:
parent
eb2cca7242
commit
efde4d468e
1 changed files with 85 additions and 1 deletions
86
mfbt/Maybe.h
86
mfbt/Maybe.h
|
|
@ -83,7 +83,15 @@ template<class T>
|
||||||
class Maybe
|
class Maybe
|
||||||
{
|
{
|
||||||
bool mIsSome;
|
bool mIsSome;
|
||||||
AlignedStorage2<T> mStorage;
|
|
||||||
|
// To support |Maybe<const Type>| we give |mStorage| the type |T| with any
|
||||||
|
// const-ness removed. That allows us to |emplace()| an object into
|
||||||
|
// |mStorage|. Since we treat the contained object as having type |T|
|
||||||
|
// everywhere else (both internally, and when exposed via public methods) the
|
||||||
|
// contained object is still treated as const once stored since |const| is
|
||||||
|
// part of |T|'s type signature.
|
||||||
|
typedef typename RemoveCV<T>::Type StorageType;
|
||||||
|
AlignedStorage2<StorageType> mStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T ValueType;
|
typedef T ValueType;
|
||||||
|
|
@ -453,6 +461,72 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Maybe<T&> {
|
||||||
|
public:
|
||||||
|
constexpr Maybe() = default;
|
||||||
|
constexpr MOZ_IMPLICIT Maybe(Nothing) {}
|
||||||
|
|
||||||
|
void emplace(T& aRef) { mValue = &aRef; }
|
||||||
|
|
||||||
|
/* Methods that check whether this Maybe contains a value */
|
||||||
|
explicit operator bool() const { return isSome(); }
|
||||||
|
bool isSome() const { return mValue; }
|
||||||
|
bool isNothing() const { return !mValue; }
|
||||||
|
|
||||||
|
T& ref() const {
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(isSome());
|
||||||
|
return *mValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* operator->() const { return &ref(); }
|
||||||
|
T& operator*() const { return ref(); }
|
||||||
|
|
||||||
|
// Deliberately not defining value and ptr accessors, as these may be
|
||||||
|
// confusing on a reference-typed Maybe.
|
||||||
|
|
||||||
|
// XXX Should we define refOr?
|
||||||
|
|
||||||
|
void reset() { mValue = nullptr; }
|
||||||
|
|
||||||
|
template <typename Func>
|
||||||
|
Maybe& apply(Func&& aFunc) {
|
||||||
|
if (isSome()) {
|
||||||
|
std::forward<Func>(aFunc)(ref());
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Func>
|
||||||
|
const Maybe& apply(Func&& aFunc) const {
|
||||||
|
if (isSome()) {
|
||||||
|
std::forward<Func>(aFunc)(ref());
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Func>
|
||||||
|
auto map(Func&& aFunc) {
|
||||||
|
Maybe<decltype(std::forward<Func>(aFunc)(ref()))> val;
|
||||||
|
if (isSome()) {
|
||||||
|
val.emplace(std::forward<Func>(aFunc)(ref()));
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Func>
|
||||||
|
auto map(Func&& aFunc) const {
|
||||||
|
Maybe<decltype(std::forward<Func>(aFunc)(ref()))> val;
|
||||||
|
if (isSome()) {
|
||||||
|
val.emplace(std::forward<Func>(aFunc)(ref()));
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* mValue = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some() creates a Maybe<T> value containing the provided T value. If T has a
|
* Some() creates a Maybe<T> value containing the provided T value. If T has a
|
||||||
* move constructor, it's used to make this as efficient as possible.
|
* move constructor, it's used to make this as efficient as possible.
|
||||||
|
|
@ -474,6 +548,13 @@ Some(T&& aValue)
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Maybe<T&> SomeRef(T& aValue) {
|
||||||
|
Maybe<T&> value;
|
||||||
|
value.emplace(aValue);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Maybe<typename RemoveCV<typename RemoveReference<T>::Type>::Type>
|
Maybe<typename RemoveCV<typename RemoveReference<T>::Type>::Type>
|
||||||
ToMaybe(T* aPtr)
|
ToMaybe(T* aPtr)
|
||||||
|
|
@ -492,6 +573,9 @@ ToMaybe(T* aPtr)
|
||||||
template<typename T> bool
|
template<typename T> bool
|
||||||
operator==(const Maybe<T>& aLHS, const Maybe<T>& aRHS)
|
operator==(const Maybe<T>& aLHS, const Maybe<T>& aRHS)
|
||||||
{
|
{
|
||||||
|
static_assert(!std::is_reference<T>::value,
|
||||||
|
"operator== is not defined for Maybe<T&>, compare values or "
|
||||||
|
"addresses explicitly instead");
|
||||||
if (aLHS.isNothing() != aRHS.isNothing()) {
|
if (aLHS.isNothing() != aRHS.isNothing()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue