Android-cuttlefish cvd tool
no_destructor.h
Go to the documentation of this file.
1#pragma once
2
3/*
4 * Copyright (C) 2019 The Android Open Source Project
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include <utility>
20
21#include "android-base/macros.h"
22
23namespace android {
24namespace base {
25
26// A wrapper that makes it easy to create an object of type T with static
27// storage duration that:
28// - is only constructed on first access
29// - never invokes the destructor
30// in order to satisfy the styleguide ban on global constructors and
31// destructors.
32//
33// Runtime constant example:
34// const std::string& GetLineSeparator() {
35// // Forwards to std::string(size_t, char, const Allocator&) constructor.
36// static const base::NoDestructor<std::string> s(5, '-');
37// return *s;
38// }
39//
40// More complex initialization with a lambda:
41// const std::string& GetSessionNonce() {
42// static const base::NoDestructor<std::string> nonce([] {
43// std::string s(16);
44// crypto::RandString(s.data(), s.size());
45// return s;
46// }());
47// return *nonce;
48// }
49//
50// NoDestructor<T> stores the object inline, so it also avoids a pointer
51// indirection and a malloc. Also note that since C++11 static local variable
52// initialization is thread-safe and so is this pattern. Code should prefer to
53// use NoDestructor<T> over:
54// - A function scoped static T* or T& that is dynamically initialized.
55// - A global base::LazyInstance<T>.
56//
57// Note that since the destructor is never run, this *will* leak memory if used
58// as a stack or member variable. Furthermore, a NoDestructor<T> should never
59// have global scope as that may require a static initializer.
60template <typename T>
62 public:
63 // Not constexpr; just write static constexpr T x = ...; if the value should
64 // be a constexpr.
65 template <typename... Args>
66 explicit NoDestructor(Args&&... args) {
67 new (storage_) T(std::forward<Args>(args)...);
68 }
69
70 // Allows copy and move construction of the contained type, to allow
71 // construction from an initializer list, e.g. for std::vector.
72 explicit NoDestructor(const T& x) { new (storage_) T(x); }
73 explicit NoDestructor(T&& x) { new (storage_) T(std::move(x)); }
74
75 NoDestructor(const NoDestructor&) = delete;
77
78 ~NoDestructor() = default;
79
80 const T& operator*() const { return *get(); }
81 T& operator*() { return *get(); }
82
83 const T* operator->() const { return get(); }
84 T* operator->() { return get(); }
85
86 const T* get() const { return reinterpret_cast<const T*>(storage_); }
87 T* get() { return reinterpret_cast<T*>(storage_); }
88
89 private:
90 alignas(T) char storage_[sizeof(T)];
91};
92
93} // namespace base
94} // namespace android
Definition: no_destructor.h:61
T & operator*()
Definition: no_destructor.h:81
NoDestructor(T &&x)
Definition: no_destructor.h:73
char storage_[sizeof(T)]
Definition: no_destructor.h:90
const T * operator->() const
Definition: no_destructor.h:83
NoDestructor(Args &&... args)
Definition: no_destructor.h:66
NoDestructor(const NoDestructor &)=delete
NoDestructor & operator=(const NoDestructor &)=delete
NoDestructor(const T &x)
Definition: no_destructor.h:72
T * operator->()
Definition: no_destructor.h:84
T * get()
Definition: no_destructor.h:87
const T & operator*() const
Definition: no_destructor.h:80
const T * get() const
Definition: no_destructor.h:86
Definition: map_ptr.h:34
std::vector< std::string_view > Args
Definition: incremental.h:28