Drake
never_destroyed.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <new>
4 #include <type_traits>
5 #include <utility>
6 
7 #include "drake/common/drake_copyable.h"
8 
9 namespace drake {
10 
11 /// Wraps an underlying type T such that its storage is a direct member field
12 /// of this object (i.e., without any indirection into the heap), but *unlike*
13 /// most member fields T's destructor is never invoked.
14 ///
15 /// This is especially useful for function-local static variables that are not
16 /// trivially destructable. We shouldn't call their destructor at program exit
17 /// because of the "indeterminate order of ... destruction" as mentioned in
18 /// cppguide's
19 /// <a href="http://drake.mit.edu/styleguide/cppguide.html#Static_and_Global_Variables">Static
20 /// and Global Variables</a> section, but other solutions to this problem place
21 /// the objects on the heap through an indirection.
22 ///
23 /// Compared with other approaches, this mechanism more clearly describes the
24 /// intent to readers, avoids "possible leak" warnings from memory-checking
25 /// tools, and is probably slightly faster.
26 ///
27 /// Example uses:
28 ///
29 /// The singleton pattern:
30 /// @code
31 /// class Singleton {
32 /// public:
33 /// DRAKE_NO_COPY_NO_MOVE_NO_ASSIGN(Singleton)
34 /// static Singleton& getInstance() {
35 /// static never_destroyed<Singleton> instance;
36 /// return instance.access();
37 /// }
38 /// private:
39 /// friend never_destroyed<Singleton>;
40 /// Singleton() = default;
41 /// };
42 /// @endcode
43 ///
44 /// A lookup table, created on demand the first time its needed, and then
45 /// reused thereafter:
46 /// @code
47 /// enum class Foo { kBar, kBaz };
48 /// Foo ParseFoo(const std::string& foo_string) {
49 /// using Dict = std::unordered_map<std::string, Foo>;
50 /// static const drake::never_destroyed<Dict> string_to_enum{
51 /// std::initializer_list<Dict::value_type>{
52 /// {"bar", Foo::kBar},
53 /// {"baz", Foo::kBaz},
54 /// }
55 /// };
56 /// return string_to_enum.access().at(foo_string);
57 /// }
58 /// @endcode
59 //
60 // The above examples are repeated in the unit test; keep them in sync.
61 template <typename T>
63  public:
65 
66  /// Passes the constructor arguments along to T using perfect forwarding.
67  template <typename... Args>
68  explicit never_destroyed(Args&&... args) {
69  // Uses "placement new" to construct a `T` in `storage_`.
70  new (&storage_) T(std::forward<Args>(args)...);
71  }
72 
73  /// Does nothing. Guaranteed!
74  ~never_destroyed() = default;
75 
76  /// Returns the underlying T reference.
77  T& access() { return *reinterpret_cast<T*>(&storage_); }
78  const T& access() const { return *reinterpret_cast<const T*>(&storage_); }
79 
80  private:
81  typename std::aligned_storage<sizeof(T), alignof(T)>::type storage_;
82 };
83 
84 } // namespace drake
never_destroyed(Args &&...args)
Passes the constructor arguments along to T using perfect forwarding.
Definition: never_destroyed.h:68
~never_destroyed()=default
Does nothing. Guaranteed!
Definition: automotive_demo.cc:89
const T & access() const
Definition: never_destroyed.h:78
#define DRAKE_NO_COPY_NO_MOVE_NO_ASSIGN(Classname)
DRAKE_NO_COPY_NO_MOVE_NO_ASSIGN deletes the special member functions for copy-construction, copy-assignment, move-construction, and move-assignment.
Definition: drake_copyable.h:33
Wraps an underlying type T such that its storage is a direct member field of this object (i...
Definition: never_destroyed.h:62
T & access()
Returns the underlying T reference.
Definition: never_destroyed.h:77