Simbody  3.6
ResetOnCopy.h
Go to the documentation of this file.
1 #ifndef SimTK_SimTKCOMMON_RESET_ON_COPY_H_
2 #define SimTK_SimTKCOMMON_RESET_ON_COPY_H_
3 
4 /* -------------------------------------------------------------------------- *
5  * Simbody(tm): SimTKcommon *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from *
8  * Simbios, the NIH National Center for Physics-Based Simulation of *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11  * *
12  * Portions copyright (c) 2015 Stanford University and the Authors. *
13  * Authors: Michael Sherman *
14  * Contributors: *
15  * *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17  * not use this file except in compliance with the License. You may obtain a *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19  * *
20  * Unless required by applicable law or agreed to in writing, software *
21  * distributed under the License is distributed on an "AS IS" BASIS, *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23  * See the License for the specific language governing permissions and *
24  * limitations under the License. *
25  * -------------------------------------------------------------------------- */
26 
28 #include <cassert>
29 #include <utility>
30 #include <memory>
31 #include <cstddef>
32 #include <type_traits>
33 
34 namespace SimTK {
35 
36 //==============================================================================
37 // RESET ON COPY
38 //==============================================================================
39 
40 // Only show the unspecialized helper class in Doxygen.
41 
44 template <class T, bool IsScalarType>
46 
99 template <class T>
100 class ResetOnCopy : public ResetOnCopyHelper<T, std::is_scalar<T>::value> {
102  // These confuse doxygen.
104  // TODO: should be possible to specialize this for arrays.
105  static_assert(!std::is_array<T>::value,
106  "ResetOnCopy<T> does not allow T to be an array. Use an array "
107  "of ResetOnCopy<E> instead, where E is the element type.");
108 
109  static_assert(!std::is_enum<T>::value,
110  "ResetOnCopy<T> does not allow T to be an enum, because resetting to "
111  "zero may be inappropriate. Use ReinitOnCopy<T> instead and "
112  "provide the desired reinitialization enumerator value.");
113 
114  static_assert(std::is_default_constructible<T>::value,
115  "ResetOnCopy<T> requires type T to have an accessible default "
116  "constructor. Use ReinitOnCopy<T> instead to construct from an "
117  "initial value.");
118 
119  static_assert(std::is_destructible<T>::value,
120  "ResetOnCopy<T> requires type T to have an accessible destructor.");
123 public:
124  using Super::Super;
125  using Super::operator=;
126 
129  ResetOnCopy() : Super() {} // same as default
130 
133  ResetOnCopy(const T& value) : Super(value) {}
134 
138  ResetOnCopy(T&& value) : Super(std::move(value)) {}
139 
143 
147  : Super(static_cast<Super&&>(source)) {} // default
148 
152  { Super::operator=(static_cast<const Super&>(ignored)); return *this; }
153 
157  { Super::operator=(static_cast<Super&&>(source)); return *this; }
158 
161  ResetOnCopy& operator=(const T& value)
162  { Super::operator=(value); return *this; }
163 
167  ResetOnCopy& operator=(T&& value)
168  { Super::operator=(std::move(value)); return *this; }
169 
171  const T& getT() const {return Super::getT();}
172 
174  T& updT() {return Super::updT();}
175 };
176 
177 //==============================================================================
178 // RESET ON COPY HELPERS
179 //==============================================================================
180 
181  // hide helpers from doxygen
183 /* ResetOnCopy helper class for built-in ("scalar") types (arithmetic,
184 character, and pointer types). We don't want to allow enums here because they
185 should always be initialized to one of their values, not necessarily zero.
186 These types are value initialized, so will be reset to zero. */
187 template <class T>
188 class ResetOnCopyHelper<T,true> {
189 public:
190  // These three are just the defaults but for debugging it is helpful to
191  // have them explicitly present to step into.
192 
193  // Default construction (note that m_value is "value initialized").
194  ResetOnCopyHelper() {}
195 
196  // Default move construction.
198  : m_value(std::move(source.m_value)) {}
199 
200  // Default move assignment.
201  ResetOnCopyHelper& operator=(ResetOnCopyHelper&& source)
202  { m_value = std::move(source.m_value); return *this; }
203 
204  // Copy constructor isn't needed here since ResetOnCopy doesn't use it.
205  ResetOnCopyHelper(const ResetOnCopyHelper&) = delete;
206 
207  // Constructor from lvalue or rvalue T sets an initial value but this
208  // initial value will not be restored on copy.
209  explicit ResetOnCopyHelper(const T& value) : m_value(value) {}
210 
211  // Make copy assignment produce the same result as if the target were
212  // value initialized; the source is ignored.
213  ResetOnCopyHelper& operator=(const ResetOnCopyHelper&)
214  { m_value = T{}; return *this; }
215 
216  // Allow assignment from an lvalue or rvalue object of type T.
217  ResetOnCopyHelper& operator=(const T& value)
218  { m_value = value; return *this; }
219 
220  // Implicit conversion to a const reference to the contained object.
221  operator const T&() const {return getT();}
222 
223  // Implicit conversion to a writable reference to the contained object.
224  operator T&() {return updT();}
225 
226  const T& getT() const {return m_value;}
227  T& updT() {return m_value;}
228 
229 private:
230  T m_value{}; // value initialize; i.e., set to zero
231 };
232 
233 
234 /* ResetOnCopy helper class specialization for any type `T` that is not a
235 built-in ("scalar") type, as long as it is DefaultConstructible and
236 Destructible. This will add `CopyConstructible` and `CopyAssignable` concepts to
237 move-only classes like `std::unique`, but those operations just reset the object
238 to its default-constructed state. */
239 template <class T>
240 class ResetOnCopyHelper<T,false> : public T {
241 public:
242  using T::T;
243  using T::operator=;
244 
245  // These three are just the defaults but for debugging it is helpful to
246  // have them explicitly present to step into.
247 
248  // Default construction (T is default constructed).
249  ResetOnCopyHelper() : T() {}
250 
251  // Default move construction.
252  ResetOnCopyHelper(ResetOnCopyHelper&& source) : T(std::move(source)) {}
253 
254  // Default move assignment.
255  ResetOnCopyHelper& operator=(ResetOnCopyHelper&& source)
256  { T::operator=(std::move(source)); return *this; }
257 
258  // Copy constructor isn't needed here since ResetOnCopy doesn't use it.
259  ResetOnCopyHelper(const ResetOnCopyHelper&) = delete;
260 
261  // Constructor from lvalue T sets an initial value but this initial value
262  // will not be restored on copy. Won't compile if T doesn't have a copy
263  // constructor.
264  explicit ResetOnCopyHelper(const T& value) : T(value) {}
265 
266  // Constructor from rvalue T sets an initial value but this initial value
267  // will not be restored on copy. Won't compile if T doesn't have a move
268  // or copy constructor.
269  explicit ResetOnCopyHelper(const T&& value) : T(std::move(value)) {}
270 
271  // Copy assignment just destroys and reconstructs this object using
272  // the default constructor for type `T`.
273  ResetOnCopyHelper& operator=(const ResetOnCopyHelper&) {
274  T* thisT = static_cast<T*>(this); // upcast to base
275  thisT->~T(); // destruct the current base object
276  new (thisT) T(); // reconstruct it with default constructor
277  return *this;
278  }
279 
280  const T& getT() const {return static_cast<const T&>(*this);}
281  T& updT() {return static_cast<T&>(*this);}
282 };
285 } // namespace SimTK
286 
287 #endif // SimTK_SimTKCOMMON_RESET_ON_COPY_H_
Ensures that a data member of type T is automatically reset to its default value upon copy constructi...
Definition: ResetOnCopy.h:100
ResetOnCopy()
Default constructor performs zero-initialization for built-in types; default initialization for class...
Definition: ResetOnCopy.h:129
ResetOnCopy & operator=(ResetOnCopy &&source)
Move assignment is simply a pass-through to the move assignment of the contained object so behaves no...
Definition: ResetOnCopy.h:156
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition: Assembler.h:37
ResetOnCopy(ResetOnCopy &&source)
Move constructor is simply a pass-through to the move constructor of the contained object so behaves ...
Definition: ResetOnCopy.h:146
STL namespace.
const T & getT() const
Return a const reference to the contained object of type T.
Definition: ResetOnCopy.h:171
ResetOnCopy(const T &value)
Construct or implicitly convert from an object of type T if there is a suitable copy constructor avai...
Definition: ResetOnCopy.h:133
ResetOnCopy & operator=(const T &value)
Assignment from an object of type T uses T&#39;s copy assignment operator if there is a suitable copy ass...
Definition: ResetOnCopy.h:161
ResetOnCopy(const ResetOnCopy &)
Copy constructor behaves identically to the default constructor; the supplied source argument is igno...
Definition: ResetOnCopy.h:142
This helper class is used only by ResetOnCopy and is specialized as necessary to support a variety of...
Definition: ResetOnCopy.h:45
Mandatory first inclusion for any Simbody source or header file.
ResetOnCopy & operator=(T &&value)
Assignment from an rvalue object of type T uses T&#39;s move assignment operator if available, otherwise uses copy assignment if available, otherwise fails to compile.
Definition: ResetOnCopy.h:167
ResetOnCopy(T &&value)
Construct or implicitly convert from an rvalue object of type T if thereis a suitable move constructo...
Definition: ResetOnCopy.h:138
T & updT()
Return a writable reference to the contained object of type T.
Definition: ResetOnCopy.h:174
ResetOnCopy & operator=(const ResetOnCopy &ignored)
Copy assignment reinitializes this object to its default-constructed condition; the source argument i...
Definition: ResetOnCopy.h:151