diff --git a/mfbt/InitializedOnce.h b/mfbt/InitializedOnce.h index acd589c760c8..842e2d4c7dce 100644 --- a/mfbt/InitializedOnce.h +++ b/mfbt/InitializedOnce.h @@ -47,10 +47,11 @@ template class InitializedOnce final { static_assert(std::is_const_v); + using MaybeType = Maybe>; public: template - explicit InitializedOnce( + explicit constexpr InitializedOnce( std::enable_if_t* = nullptr) {} @@ -58,7 +59,7 @@ class InitializedOnce final { // arguments. The default constructor should only be available conditionally // and is declared above. template - explicit InitializedOnce(Arg0&& aArg0, Args&&... aArgs) + explicit constexpr InitializedOnce(Arg0&& aArg0, Args&&... aArgs) : mMaybe{Some(std::remove_const_t{std::forward(aArg0), std::forward(aArgs)...})} { MOZ_ASSERT(ValueCheckPolicy::Check(*mMaybe)); @@ -77,8 +78,8 @@ class InitializedOnce final { DestroyWhenVal == DestroyWhen::EarlyAllowed); MOZ_ASSERT(!mWasReset); MOZ_ASSERT(!mMaybe); - mMaybe.~Maybe>(); - new (&mMaybe) Maybe{std::move(aOther.mMaybe)}; + mMaybe.~MaybeType(); + new (&mMaybe) MaybeType{std::move(aOther.mMaybe)}; #ifdef DEBUG aOther.mWasReset = true; #endif @@ -86,7 +87,7 @@ class InitializedOnce final { } template - std::enable_if_t init( + constexpr std::enable_if_t init( Args&&... aArgs) { MOZ_ASSERT(mMaybe.isNothing()); MOZ_ASSERT(!mWasReset); @@ -94,12 +95,12 @@ class InitializedOnce final { MOZ_ASSERT(ValueCheckPolicy::Check(*mMaybe)); } - explicit operator bool() const { return isSome(); } - bool isSome() const { return mMaybe.isSome(); } - bool isNothing() const { return mMaybe.isNothing(); } + constexpr explicit operator bool() const { return isSome(); } + constexpr bool isSome() const { return mMaybe.isSome(); } + constexpr bool isNothing() const { return mMaybe.isNothing(); } - T& operator*() const { return *mMaybe; } - T* operator->() const { return mMaybe.operator->(); } + constexpr T& operator*() const { return *mMaybe; } + constexpr T* operator->() const { return mMaybe.operator->(); } template std::enable_if_t @@ -127,7 +128,7 @@ class InitializedOnce final { } private: - Maybe> mMaybe; + MaybeType mMaybe; #ifdef DEBUG bool mWasReset = false; #endif diff --git a/mfbt/tests/gtest/TestInitializedOnce.cpp b/mfbt/tests/gtest/TestInitializedOnce.cpp index c79f0418c72c..c6edd8308883 100644 --- a/mfbt/tests/gtest/TestInitializedOnce.cpp +++ b/mfbt/tests/gtest/TestInitializedOnce.cpp @@ -27,10 +27,8 @@ void AssertIsNothing(const T& aVal) { ASSERT_TRUE(aVal.isNothing()); } -// XXX TODO Should be true once Bug ... ensures this for Maybe. -// static_assert(std::is_trivially_destructible_v>); -// static_assert(std::is_trivially_default_constructible_v>); +static_assert(std::is_trivially_destructible_v>); +static_assert(std::is_trivially_destructible_v>); static_assert(!std::is_copy_constructible_v>); static_assert(!std::is_copy_assignable_v>); @@ -75,7 +73,7 @@ static_assert( test_has_init_method(kPtrInitializedOnceIntLazyInitAllowResettable)); struct MoveOnly { - explicit MoveOnly(int aValue) : mValue{aValue} {} + explicit constexpr MoveOnly(int aValue) : mValue{aValue} {} MoveOnly(MoveOnly&&) = default; MoveOnly& operator=(MoveOnly&&) = default; @@ -89,8 +87,16 @@ constexpr int testValue = 32; TEST(InitializedOnce, ImmediateInit) { - const InitializedOnce val{testValue}; + constexpr InitializedOnce val{testValue}; + // compile-time assertions + static_assert(val); + static_assert(val.isSome()); + static_assert(!val.isNothing()); + static_assert(testValue == (*val).mValue); + static_assert(testValue == val->mValue); + + // run-time assertions AssertIsSome(val); ASSERT_EQ(testValue, (*val).mValue); ASSERT_EQ(testValue, val->mValue);