1 // Copyright 2021 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef LIB_LAZY_INIT_INTERNAL_STORAGE_H_ 6 #define LIB_LAZY_INIT_INTERNAL_STORAGE_H_ 7 8 #include <lib/lazy_init/options.h> 9 10 #include <type_traits> 11 #include <utility> 12 13 #include "assert.h" 14 15 namespace lazy_init { 16 namespace internal { 17 18 // Empty type that is trivially constructible/destructible. 19 struct Empty {}; 20 21 // Lazy-initialized storage type for trivially destructible value types. 22 template <typename T, bool = std::is_trivially_destructible_v<T>> 23 union LazyInitStorage { LazyInitStorage()24 constexpr LazyInitStorage() : empty{} {} 25 26 // Trivial destructor required so that the overall union is also trivially 27 // destructible. 28 ~LazyInitStorage() = default; 29 30 constexpr T& operator*() { return value; } 31 constexpr T* operator->() { return &value; } GetStorageAddress()32 constexpr T* GetStorageAddress() { return &value; } 33 34 constexpr const T& operator*() const { return value; } 35 constexpr const T* operator->() const { return &value; } GetStorageAddress()36 constexpr const T* GetStorageAddress() const { return &value; } 37 38 Empty empty; 39 T value; 40 }; 41 42 // Lazy-initialized storage type for non-trivially destructible value types. 43 template <typename T> 44 union LazyInitStorage<T, false> { 45 constexpr LazyInitStorage() : empty{} {} 46 47 // Non-trivial destructor required when at least one variant is non- 48 // trivially destructible, making the overall union also non-trivially 49 // destructible. 50 ~LazyInitStorage() {} 51 52 constexpr T& operator*() { return value; } 53 constexpr T* operator->() { return &value; } 54 constexpr T* GetStorageAddress() { return &value; } 55 56 constexpr const T& operator*() const { return value; } 57 constexpr const T* operator->() const { return &value; } 58 constexpr const T* GetStorageAddress() const { return &value; } 59 60 Empty empty; 61 T value; 62 }; 63 64 } // namespace internal 65 } // namespace lazy_init 66 #endif // LIB_LAZY_INIT_INTERNAL_STORAGE_H_ 67