Simbody  3.7
ReinitOnCopy.h
Go to the documentation of this file.
1 #ifndef SimTK_SimTKCOMMON_REINIT_ON_COPY_H_
2 #define SimTK_SimTKCOMMON_REINIT_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 // REINIT ON COPY
38 //==============================================================================
39 
40 // Only show the unspecialized helper class in Doxygen.
41 
44 template <class T, bool IsScalarType>
46 
93 template <class T>
94 class ReinitOnCopy : public ReinitOnCopyHelper<T, std::is_scalar<T>::value> {
96  // These confuse doxygen.
98  // TODO: should be possible to specialize this for arrays.
99  static_assert(!std::is_array<T>::value,
100  "ReinitOnCopy<T> does not allow T to be an array. Use an array "
101  "of ReinitOnCopy<E> instead, where E is the element type.");
102 
103  static_assert( std::is_copy_constructible<T>::value
104  && std::is_copy_assignable<T>::value,
105  "ReinitOnCopy<T> requires type T to have an accessible copy "
106  "constructor and copy assignment operator. Use ResetOnCopy<T> instead "
107  "to reinitialize using only default construction.");
108 
109  static_assert(std::is_destructible<T>::value,
110  "ReinitOnCopy<T> requires type T to have an accessible destructor.");
113 public:
114  using Super::Super;
115  using Super::operator=;
116 
118  ReinitOnCopy() = delete;
119 
122  ReinitOnCopy(const T& value) : Super(value) {}
123 
127  ReinitOnCopy(T&& value) : Super(std::move(value)) {}
128 
132  ReinitOnCopy(const ReinitOnCopy& source)
133  : Super(static_cast<const Super&>(source)) {}
134 
138  : Super(static_cast<Super&&>(source)) {} // default
139 
143  { Super::operator=(static_cast<const Super&>(ignored)); return *this; }
144 
148  { Super::operator=(static_cast<Super&&>(source)); return *this; }
149 
153  ReinitOnCopy& operator=(const T& value)
154  { Super::operator=(value); return *this; }
155 
159  ReinitOnCopy& operator=(T&& value)
160  { Super::operator=(std::move(value)); return *this; }
161 
163  const T& getT() const {return Super::getT();}
164 
166  T& updT() {return Super::updT();}
167 
169  const T& getReinitT() const {return Super::getReinitT();}
170 
173  T& updReinitT() {return Super::updReinitT();}
174 };
175 
176 //==============================================================================
177 // REINIT ON COPY HELPERS
178 //==============================================================================
179 
180  // hide helpers from doxygen
182 /* ReinitOnCopy helper class for built-in types (integral or floating point).
183 These types are value initialized, so will be reset to zero. */
184 template <class T>
185 class ReinitOnCopyHelper<T,true> {
186 public:
187  // These three are just the defaults but for debugging it is helpful to
188  // have them explicitly present to step into.
189 
190  // Default construction (note that members are "value initialized").
191  ReinitOnCopyHelper() {}
192 
193  // Copy constructor sets the value and remembered initial value to the
194  // initial value in the source, using type `T`'s copy constructor. The
195  // current value of the source is ignored.
196  ReinitOnCopyHelper(const ReinitOnCopyHelper& source)
197  : ReinitOnCopyHelper(source.m_reinitValue) {}
198 
199  // Default move construction.
200  ReinitOnCopyHelper(ReinitOnCopyHelper&& source)
201  : m_value(std::move(source.m_value)),
202  m_reinitValue(std::move(source.m_reinitValue)) {}
203 
204  // Constructor from lvalue or rvalue `T` sets the value and remembered
205  // initial value to the given value, using type `T`'s copy constructor.
206  explicit ReinitOnCopyHelper(const T& value)
207  : m_value(value), m_reinitValue(value) {}
208 
209  // Move assignment moves the *value* from source to `this` but does not
210  // move the recorded initial value which may differ.
211  ReinitOnCopyHelper& operator=(ReinitOnCopyHelper&& source)
212  { m_value = std::move(source.m_value); return *this; }
213 
214  // Copy assignment resets the current value to the remembered initial value
215  // using type `T`'s copy assignment operator. The source is ignored.
216  ReinitOnCopyHelper& operator=(const ReinitOnCopyHelper&)
217  { m_value = m_reinitValue; return *this; }
218 
219  // Allow assignment from an lvalue or rvalue object of type T; affects only
220  // the current value. Uses built-in type `T`'s copy assignment operator.
221  ReinitOnCopyHelper& operator=(const T& value)
222  { m_value = value; return *this; }
223 
224  // Implicit conversion to a const reference to the contained object of
225  // type `T`.
226  operator const T&() const {return getT();}
227 
228  // Implicit conversion to a writable reference to the contained object of
229  // type `T`.
230  operator T&() {return updT();}
231 
232  const T& getT() const {return m_value;}
233  T& updT() {return m_value;}
234 
235  // Return a const reference to the stored initial value.
236  const T& getReinitT() const {return m_reinitValue;}
237 
238  // Return a writable reference to the stored initial value. Use of this
239  // should be restricted to constructors.
240  T& updReinitT() {return m_reinitValue;}
241 
242 private:
243  T m_value{}; // note "value initialization"; i.e. zero
244  const T m_reinitValue{};
245 };
246 
247 
248 /* ReinitOnCopy helper class specialization for any type `T` that is not a
249 built-in ("scalar") type and that is `CopyConstructible` and `CopyAssignable`.
250 Those operators are used to reinitialize the object to a stored initial value
251 when copy constructor or copy assignment is performed. */
252 template <class T>
253 class ReinitOnCopyHelper<T,false> : public T {
254 public:
255  using T::T;
256  using T::operator=;
257 
258  // Default construction (T and the stored initial value are default
259  // constructed).
260  ReinitOnCopyHelper() : T(), m_reinitValue() {}
261 
262  // Move construction moves both the value and initial value from the
263  // source object. This is the same as default move construction.
264  ReinitOnCopyHelper(ReinitOnCopyHelper&& source)
265  : T(std::move(source)), m_reinitValue(std::move(source.m_reinitValue)) {}
266 
267  // Constructor from lvalue `T` sets the value and remembered initial value
268  // to the given value, using type `T`'s copy constructor.
269  explicit ReinitOnCopyHelper(const T& value)
270  : T(value), m_reinitValue(value) {}
271 
272  // Constructor from rvalue `T` sets the value and remembered initial value
273  // to the given value, using type `T`'s move and copy constructors.
274  explicit ReinitOnCopyHelper(T&& value)
275  : T(value), m_reinitValue(static_cast<const T&>(*this)) {} // careful!
276 
277  // Copy constructor sets the value and remembered initial value to the
278  // initial value in the source, using type `T`'s copy constructor. The
279  // current value of the source is ignored.
280  ReinitOnCopyHelper(const ReinitOnCopyHelper& source)
281  : ReinitOnCopyHelper(source.m_reinitValue) {}
282 
283  // Move assignment moves the *value* from source to `this` but does not
284  // move the recorded initial value which may differ.
285  ReinitOnCopyHelper& operator=(ReinitOnCopyHelper&& source)
286  { T::operator=(std::move(source)); return *this; }
287 
288  // Copy assignment resets the current value to the remembered initial value
289  // using type `T`'s copy assignment operator. The source is ignored.
290  ReinitOnCopyHelper& operator=(const ReinitOnCopyHelper&)
291  { T::operator=(m_reinitValue); return *this; }
292 
293  // Allow assignment from an lvalue object of type T; affects only the
294  // current value. Uses type `T`'s copy assignment operator.
295  ReinitOnCopyHelper& operator=(const T& value)
296  { T::operator=(value); return *this; }
297 
298  // Allow assignment from an rvalue object of type T; affects only the
299  // current value. Uses type `T`'s move assignment operator.
300  ReinitOnCopyHelper& operator=(T&& value)
301  { T::operator=(std::move(value)); return *this; }
302 
303  const T& getT() const {return static_cast<const T&>(*this);}
304  T& updT() {return static_cast<T&>(*this);}
305 
306  // Return a const reference to the stored initial value.
307  const T& getReinitT() const {return m_reinitValue;}
308 
309  // Return a writable reference to the stored initial value. Use of this
310  // should be restricted to constructors.
311  T& updReinitT() {return m_reinitValue;}
312 
313 private:
314  // The remembered initial value is set to the already-constructed
315  // base value in case we used one of the base constructors. This uses
316  // the base class copy constructor.
317  const T m_reinitValue {static_cast<const T&>(*this)};
318 };
319 
322 } // namespace SimTK
323 
324 #endif // SimTK_SimTKCOMMON_REINIT_ON_COPY_H_
325 
ReinitOnCopy & operator=(T &&value)
Assignment from an rvalue object of type T uses T&#39;s move or copy assignment operator; affects only th...
Definition: ReinitOnCopy.h:159
ReinitOnCopy & operator=(const ReinitOnCopy &ignored)
Copy assignment reinitializes this object to its original condition; the source argument is ignored...
Definition: ReinitOnCopy.h:142
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition: Assembler.h:37
ReinitOnCopy(T &&value)
Construct or implicitly convert from an rvalue object of type T. This sets both the current and remem...
Definition: ReinitOnCopy.h:127
STL namespace.
const T & getT() const
Return a const reference to the contained object of type T.
Definition: ReinitOnCopy.h:163
T & updReinitT()
(Advanced) Return a writable reference to the stored initial value. Use of this should be rare and re...
Definition: ReinitOnCopy.h:173
ReinitOnCopy & operator=(const T &value)
Assignment from an object of type T uses T&#39;s copy assignment operator; affects only the current value...
Definition: ReinitOnCopy.h:153
Mandatory first inclusion for any Simbody source or header file.
const T & getReinitT() const
(Advanced) Return a const reference to the stored initial value.
Definition: ReinitOnCopy.h:169
Ensures that a data member of type T is automatically reinitialized to a given initial value upon cop...
Definition: ReinitOnCopy.h:94
T & updT()
Return a writable reference to the contained object of type T.
Definition: ReinitOnCopy.h:166
ReinitOnCopy(const ReinitOnCopy &source)
Copy constructor sets the value and remembered initial value to the initial value in the source...
Definition: ReinitOnCopy.h:132
ReinitOnCopy(ReinitOnCopy &&source)
Move constructor is simply a pass-through to the move constructor of the contained object for both th...
Definition: ReinitOnCopy.h:137
This helper class is used only by ReinitOnCopy and is specialized as necessary to support a variety o...
Definition: ReinitOnCopy.h:45
ReinitOnCopy(const T &value)
Construct or implicitly convert from an object of type T. This sets both the current and remembered i...
Definition: ReinitOnCopy.h:122
ReinitOnCopy & operator=(ReinitOnCopy &&source)
Move assignment uses type T&#39;s move assignment for the current value but does not change the remembere...
Definition: ReinitOnCopy.h:147
ReinitOnCopy()=delete
Default constructor is deleted; use ResetOnCopy instead.