Gazebo Utils

API Reference

2.2.0
NeverDestroyed< T > Class Template Reference

#include <NeverDestroyed.hh>

Public Member Functions

template<typename... Args>
 NeverDestroyed (Args &&... args)
 Passes the constructor arguments along to T using perfect forwarding. More...
 
 NeverDestroyed (const NeverDestroyed &)=delete
 Deleted copy constructor. More...
 
 NeverDestroyed (NeverDestroyed &&)=delete
 Deleted move constructor. More...
 
 ~NeverDestroyed ()=default
 Does nothing. Guaranteed! More...
 
T & Access ()
 Returns the underlying T reference. More...
 
const T & Access () const
 
NeverDestroyedoperator= (const NeverDestroyed &)=delete
 Deleted copy assignment constructor. More...
 
NeverDestroyedoperator= (NeverDestroyed &&) noexcept=delete
 Deleted move assignment constructor. More...
 

Detailed Description

template<typename T>
class gz::utils::NeverDestroyed< T >

Originally copied from https://github.com/RobotLocomotion/drake/blob/v0.36.0/common/never_destroyed.h Originally licensed BSD 3-Clause (https://github.com/RobotLocomotion/drake/blob/v0.36.0/LICENSE.TXT) Re-licensed Apache-2.0 with permission from: jwnimmer-tri (https://github.com/gazebosim/gz-utils/pull/31#issuecomment-989173512)

Wraps an underlying type T such that its storage is a direct member field of this object (i.e., without any indirection into the heap), but unlike most member fields T's destructor is never invoked.

This is especially useful for function-local static variables that are not trivially destructable. We shouldn't call their destructor at program exit because of the "indeterminate order of ... destruction" as mentioned in cppguide's Static and Global Variables section, but other solutions to this problem place the objects on the heap through an indirection.

Compared with other approaches, this mechanism more clearly describes the intent to readers, avoids "possible leak" warnings from memory-checking tools, and is probably slightly faster.

Example uses:

The singleton pattern:

class Singleton
{
public:
Singleton(const Singleton&) = delete;
void operator=(const Singleton&) = delete;
Singleton(Singleton&&) = delete;
void operator=(Singleton&&) = delete;
static Singleton& getInstance()
{
static NeverDestroyed<Singleton> instance;
return instance.access();
}
private:
friend NeverDestroyed<Singleton>;
Singleton() = default;
};

A lookup table, created on demand the first time its needed, and then reused thereafter:

enum class Foo { kBar, kBaz };
Foo ParseFoo(const std::string& foo_string)
{
static const NeverDestroyed<Dict> string_to_enum
{
{
{"bar", Foo::kBar},
{"baz", Foo::kBaz},
}
};
return string_to_enum.access().at(foo_string);
}

In cases where computing the static data is more complicated than an initializer_list, you can use a temporary lambda to populate the value:

const std::vector<double>& GetConstantMagicNumbers()
{
static const NeverDestroyed<std::vector<double>> result
{
[]()
{
std::mt19937 random_generator;
for (int i = 0; i < 10; ++i)
{
double new_value = random_generator();
prototype.push_back(new_value);
}
return prototype;
}()
};
return result.access();
}

Note in particular the () after the lambda. That causes it to be invoked.

Constructor & Destructor Documentation

◆ NeverDestroyed() [1/3]

NeverDestroyed ( Args &&...  args)
inlineexplicit

Passes the constructor arguments along to T using perfect forwarding.

◆ ~NeverDestroyed()

~NeverDestroyed ( )
default

Does nothing. Guaranteed!

◆ NeverDestroyed() [2/3]

NeverDestroyed ( const NeverDestroyed< T > &  )
delete

Deleted copy constructor.

◆ NeverDestroyed() [3/3]

NeverDestroyed ( NeverDestroyed< T > &&  )
delete

Deleted move constructor.

Member Function Documentation

◆ Access() [1/2]

T& Access ( )
inline

Returns the underlying T reference.

◆ Access() [2/2]

const T& Access ( ) const
inline

◆ operator=() [1/2]

NeverDestroyed& operator= ( const NeverDestroyed< T > &  )
delete

Deleted copy assignment constructor.

◆ operator=() [2/2]

NeverDestroyed& operator= ( NeverDestroyed< T > &&  )
deletenoexcept

Deleted move assignment constructor.


The documentation for this class was generated from the following file: