MaybeStorageBase.h (2921B)
1 /* -*- Mode: C++; tab-width: 2; 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 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* Internal storage class used e.g. by Maybe and Result. This file doesn't 8 * contain any public declarations. */ 9 10 #ifndef mfbt_MaybeStorageBase_h 11 #define mfbt_MaybeStorageBase_h 12 13 #include <type_traits> 14 #include <utility> 15 16 namespace mozilla::detail { 17 18 template <typename T> 19 constexpr bool IsTriviallyDestructibleAndCopyable = 20 std::is_trivially_destructible_v<T> && 21 (std::is_trivially_copy_constructible_v<T> || 22 !std::is_copy_constructible_v<T>); 23 24 template <typename T, bool TriviallyDestructibleAndCopyable = 25 IsTriviallyDestructibleAndCopyable<T>> 26 struct MaybeStorageBase; 27 28 template <typename T> 29 struct MaybeStorageBase<T, false> { 30 protected: 31 using NonConstT = std::remove_const_t<T>; 32 33 union Union { 34 Union() {} 35 explicit Union(const T& aVal) : val{aVal} {} 36 template <typename U, 37 typename = std::enable_if_t<std::is_move_constructible_v<U>>> 38 explicit Union(U&& aVal) : val{std::forward<U>(aVal)} {} 39 template <typename... Args> 40 explicit Union(std::in_place_t, Args&&... aArgs) 41 : val{std::forward<Args>(aArgs)...} {} 42 43 ~Union() {} 44 45 NonConstT val; 46 } mStorage; 47 48 public: 49 constexpr MaybeStorageBase() = default; 50 explicit MaybeStorageBase(const T& aVal) : mStorage{aVal} {} 51 explicit MaybeStorageBase(T&& aVal) : mStorage{std::move(aVal)} {} 52 template <typename... Args> 53 explicit MaybeStorageBase(std::in_place_t, Args&&... aArgs) 54 : mStorage{std::in_place, std::forward<Args>(aArgs)...} {} 55 56 const T* addr() const { return &mStorage.val; } 57 T* addr() { return &mStorage.val; } 58 }; 59 60 template <typename T> 61 struct MaybeStorageBase<T, true> { 62 protected: 63 using NonConstT = std::remove_const_t<T>; 64 65 union Union { 66 constexpr Union() : empty() {} 67 constexpr explicit Union(const T& aVal) : val{aVal} {} 68 constexpr explicit Union(T&& aVal) : val{std::move(aVal)} {} 69 template <typename... Args> 70 constexpr explicit Union(std::in_place_t, Args&&... aArgs) 71 : val{std::forward<Args>(aArgs)...} {} 72 73 NonConstT val; 74 char empty; 75 } mStorage; 76 77 public: 78 constexpr MaybeStorageBase() = default; 79 constexpr explicit MaybeStorageBase(const T& aVal) : mStorage{aVal} {} 80 constexpr explicit MaybeStorageBase(T&& aVal) : mStorage{std::move(aVal)} {} 81 82 template <typename... Args> 83 constexpr explicit MaybeStorageBase(std::in_place_t, Args&&... aArgs) 84 : mStorage{std::in_place, std::forward<Args>(aArgs)...} {} 85 86 constexpr const T* addr() const { return &mStorage.val; } 87 constexpr T* addr() { return &mStorage.val; } 88 }; 89 90 } // namespace mozilla::detail 91 92 #endif