2 * Copyright 2017 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
27 * When you need a Meyers singleton that will not get destructed, even at
28 * shutdown, and you also want the object stored inline.
32 * void doSomethingWithExpensiveData();
34 * void doSomethingWithExpensiveData() {
35 * static const Indestructible<map<string, int>> data{
36 * map<string, int>{{"key1", 17}, {"key2", 19}, {"key3", 23}},
38 * callSomethingTakingAMapByRef(*data);
41 * This should be used only for Meyers singletons, and, even then, only when
42 * the instance does not need to be destructed ever.
44 * This should not be used more generally, e.g., as member fields, etc.
46 * This is designed as an alternative, but with one fewer allocation at
47 * construction time and one fewer pointer dereference at access time, to the
48 * Meyers singleton pattern of:
50 * void doSomethingWithExpensiveData() {
51 * static const auto data = // never `delete`d
52 * new map<string, int>{{"key1", 17}, {"key2", 19}, {"key3", 23}};
53 * callSomethingTakingAMapByRef(*data);
58 class Indestructible final {
61 template <typename S = T, typename = decltype(S())>
62 constexpr Indestructible() noexcept(noexcept(T())) {}
64 template <typename... Args, typename = decltype(T(std::declval<Args&&>()...))>
65 explicit constexpr Indestructible(Args&&... args) noexcept(
66 noexcept(T(std::declval<Args&&>()...)))
67 : storage_(std::forward<Args>(args)...) {}
69 ~Indestructible() = default;
71 Indestructible(Indestructible const&) = delete;
72 Indestructible& operator=(Indestructible const&) = delete;
74 Indestructible(Indestructible&& other) noexcept(
75 noexcept(T(std::declval<T&&>())))
76 : storage_(std::move(other.storage_.value)) {
79 Indestructible& operator=(Indestructible&& other) noexcept(
80 noexcept(T(std::declval<T&&>()))) {
81 storage_.value = std::move(other.storage_.value);
87 return &storage_.value;
89 T const* get() const noexcept {
91 return &storage_.value;
93 T& operator*() noexcept { return *get(); }
94 T const& operator*() const noexcept { return *get(); }
95 T* operator->() noexcept { return get(); }
96 T const* operator->() const noexcept { return get(); }
99 void check() const noexcept {
106 template <typename S = T, typename = decltype(S())>
107 constexpr Storage() noexcept(noexcept(T())) : value() {}
111 typename = decltype(T(std::declval<Args&&>()...))>
112 explicit constexpr Storage(Args&&... args) noexcept(
113 noexcept(T(std::declval<Args&&>()...)))
114 : value(std::forward<Args>(args)...) {}