Drake
Drake C++ Documentation
reset_on_copy< T > Class Template Reference

Detailed Description

template<typename T>
class drake::reset_on_copy< T >

Type wrapper that performs value-initialization on copy construction or assignment.

Rather than copying the source supplied for copy construction or copy assignment, this wrapper instead value-initializes the destination object. Move assignment and construction preserve contents in the destination as usual, but reset the source to its value-initialized value.

Only types T that satisfy std::is_scalar<T> are currently permitted: integral and floating point types, enums, and pointers. Value initialization means the initialization performed when a variable is constructed with an empty initializer {}. For the restricted set of types we support, that just means that numeric types are set to zero and pointer types are set to nullptr. Also, all the methods here are noexcept due to the std::is_scalar<T> restriction. See http://en.cppreference.com/w/cpp/language/value_initialization.

Background:

It is preferable to use default copy construction for classes whenever possible because it avoids difficult-to-maintain enumeration of member fields in bespoke copy constructors. The presence of fields that must be reset to zero in the copy (counters, for example) prevents use of default copy construction. Similarly, pointers that would be invalid in the copy need to be set to null to avoid stale references. By wrapping those problematic data members in this adapter, default copy construction can continue to be used, with all data members copied properly except the designated ones, which are value-initialized instead. The resetting of the source on move doesn't change semantics since the condition of the source after a move is generally undefined. It is instead opportunistic good hygiene for early detection of bugs, taking advantage of the fact that we know type T can be value-initialized. See reset_after_move for more discussion.

Example:

class Foo {
 public:
  DRAKE_DEFAULT_COPY_AND_MOVE_AND_ASSIGN(Foo);
  Foo() = default;
 private:
  std::vector<int> items_;
  reset_on_copy<int> use_count_;
};

When copying from Foo, the new object will contain a copy of items_ but use_count_ will be zero. If Foo had not used the reset_on_copy wrapper, use_count_ would have been copied also, which we're assuming is not the desired behavior here.

Warning
Even if you initialize a reset_on_copy member to a non-zero value using an initializer like reset_on_copy<int> some_member_{5} it will be reset to zero, not reinitialized to 5 when copied.
Note
Enum types T are permitted, but be aware that they will be reset to zero, regardless of whether 0 is one of the specified enumeration values.
Template Parameters
Tmust satisfy std::is_scalar<T>.
See also
reset_after_move

#include <drake/common/reset_on_copy.h>

Public Member Functions

 reset_on_copy () noexcept(std::is_nothrow_default_constructible_v< T >)
 Constructs a reset_on_copy<T> with a value-initialized wrapped value. More...
 
 reset_on_copy (const T &value) noexcept(std::is_nothrow_copy_constructible_v< T >)
 Constructs a reset_on_copy<T> with a copy of the given value. More...
 
 reset_on_copy (T &&value) noexcept(std::is_nothrow_move_constructible_v< T >)
 Constructs a reset_on_copy<T> with the given wrapped value, by move construction if possible. More...
 
Implements copy/move construction and assignment.

These make reset_on_copy objects CopyConstructible, CopyAssignable, MoveConstructible, and MoveAssignable.

 reset_on_copy (const reset_on_copy &) noexcept(std::is_nothrow_default_constructible_v< T >)
 Copy constructor just value-initializes instead; the source is ignored. More...
 
reset_on_copyoperator= (const reset_on_copy &source) noexcept(std::is_nothrow_destructible_v< T > &&std::is_nothrow_default_constructible_v< T >)
 Copy assignment just destructs the contained value and then value-initializes it, except for self-assignment which does nothing. More...
 
 reset_on_copy (reset_on_copy &&source) noexcept(std::is_nothrow_move_constructible_v< T > &&std::is_nothrow_destructible_v< T > &&std::is_nothrow_default_constructible_v< T >)
 Move construction uses T's move constructor, then destructs and value initializes the source. More...
 
reset_on_copyoperator= (reset_on_copy &&source) noexcept(std::is_nothrow_move_assignable_v< T > &&std::is_nothrow_destructible_v< T > &&std::is_nothrow_default_constructible_v< T >)
 Move assignment uses T's move assignment, then destructs and value initializes the source, except for self-assignment which does nothing. More...
 
Implicit conversion operators to make reset_on_copy<T> act

as the wrapped type.

 operator T & () noexcept
 
 operator const T & () const noexcept
 
Dereference operators if T is a pointer type.

If type T is a pointer, these exist and return the pointed-to object.

For non-pointer types these methods are not instantiated.

template<typename T1 = T>
std::enable_if_t< std::is_pointer_v< T1 >, T > operator-> () const noexcept
 
template<typename T1 = T>
std::enable_if_t< std::is_pointer_v< T1 >, std::add_lvalue_reference_t< std::remove_pointer_t< T > > > operator * () const noexcept
 

Constructor & Destructor Documentation

◆ reset_on_copy() [1/5]

reset_on_copy ( )
noexcept

Constructs a reset_on_copy<T> with a value-initialized wrapped value.

◆ reset_on_copy() [2/5]

reset_on_copy ( const T &  value)
noexcept

Constructs a reset_on_copy<T> with a copy of the given value.

This is an implicit conversion, so that reset_on_copy<T> behaves more like the unwrapped type.

◆ reset_on_copy() [3/5]

reset_on_copy ( T &&  value)
noexcept

Constructs a reset_on_copy<T> with the given wrapped value, by move construction if possible.

This is an implicit conversion, so that reset_on_copy<T> behaves more like the unwrapped type.

◆ reset_on_copy() [4/5]

reset_on_copy ( const reset_on_copy< T > &  )
noexcept

Copy constructor just value-initializes instead; the source is ignored.

◆ reset_on_copy() [5/5]

reset_on_copy ( reset_on_copy< T > &&  source)
noexcept

Move construction uses T's move constructor, then destructs and value initializes the source.

Member Function Documentation

◆ operator *()

std::enable_if_t<std::is_pointer_v<T1>, std::add_lvalue_reference_t<std::remove_pointer_t<T> > > operator * ( ) const
noexcept

◆ operator const T &()

operator const T & ( ) const
noexcept

◆ operator T &()

operator T & ( )
noexcept

◆ operator->()

std::enable_if_t<std::is_pointer_v<T1>, T> operator-> ( ) const
noexcept

◆ operator=() [1/2]

reset_on_copy& operator= ( const reset_on_copy< T > &  source)
noexcept

Copy assignment just destructs the contained value and then value-initializes it, except for self-assignment which does nothing.

The source argument is otherwise ignored.

◆ operator=() [2/2]

reset_on_copy& operator= ( reset_on_copy< T > &&  source)
noexcept

Move assignment uses T's move assignment, then destructs and value initializes the source, except for self-assignment which does nothing.

The source argument is otherwise ignored.


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