Drake
copyable_unique_ptr.h
Go to the documentation of this file.
1 #pragma once
2 
3 /* Portions copyright (c) 2015 Stanford University and the Authors.
4  Authors: Michael Sherman
5 
6 Licensed under the Apache License, Version 2.0 (the "License"); you may
7 not use this file except in compliance with the License. You may obtain a
8 copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
9 
10 (Adapted from Simbody's ClonePtr class.)
11  */
12 
13 #include <cstddef>
14 #include <iostream>
15 #include <memory>
16 #include <utility>
17 
20 
21 namespace drake {
22 
23 /** @cond */
24 
25 namespace copyable_unique_ptr_detail {
26 
27 // This uses SFINAE to classify a particular class as "copyable". There are two
28 // overloads of the `is_copyable_unique_ptr_compatible_helper` struct: one is
29 // the default implementation and the other relies on the SFINAE and copyable
30 // test.
31 //
32 // The default overload reports that a class is _not_ copyable. Only if the
33 // class being queried passes the copyable test, will the second overload get
34 // created. It defines value to be true. The second overload is a more specific
35 // match to the helper invocation, so, if it exists, it will be instantiated by
36 // preference and report a true value.
37 
38 template <typename V, class>
39 struct is_copyable_unique_ptr_compatible_helper : std::false_type {};
40 
41 // This is the specific overload. The copyable condition is that it is
42 // "cloneable" or has a copy constructor.
43 template <typename V>
44 struct is_copyable_unique_ptr_compatible_helper<
45  V, typename std::enable_if<is_cloneable<V>::value ||
46  std::is_copy_constructible<V>::value>::type>
47  : std::true_type {};
48 
49 
50 } // namespace copyable_unique_ptr_detail
51 /** @endcond */
52 
53 /**
54  Test for determining if an arbitrary class is compatible with the
55  copyable_unique_ptr. For a class to be compatible with the copy_unique_ptr,
56  it must be copy constructible or "cloneable" (see @ref is_cloneable_doc
57  "is_cloneable"). Usage:
58 
59  @code
60  is_copyable_unique_ptr_compatible<TestClass>::value
61  @endcode
62 
63  Evaluates to true if compatible, false otherwise. This can be used in run-time
64  test, `static_assert`s, and in SFINAE voodoo.
65 
66  @see copyable_unique_ptr
67  @see is_cloneable
68  */
69 template <typename T>
71  copyable_unique_ptr_detail::is_copyable_unique_ptr_compatible_helper<T,
72  void>;
73 
74 /** A smart pointer with deep copy semantics.
75 
76  This is _similar_ to `std::unique_ptr` in that it does not permit shared
77  ownership of the contained object. However, unlike `std::unique_ptr`,
78  %copyable_unique_ptr supports copy and assignment operations, by insisting that
79  the contained object be "copyable".
80  To be copyable, the class must have either a public copy constructor, or it
81  must be "cloneable" (see @ref is_cloneable_doc "is_cloneable" for definition).
82  A class can be tested for compatibility using the
83  @ref is_copyable_unique_ptr_compatible struct.
84 
85  Generally, the API is modeled as closely as possible on the C++ standard
86  `std::unique_ptr` API and %copyable_unique_ptr<T> is interoperable with
87  `unique_ptr<T>` wherever that makes sense. However, there are some differences:
88  1. It always uses a default deleter.
89  2. There is no array version.
90  3. To allow for future copy-on-write optimizations, there is a distinction
91  between writable and const access, the get() method is modified to return
92  only a const pointer, with get_mutable() added to return a writable pointer.
93 
94  This class is entirely inline and has no computational or
95  space overhead except when copying is required; it contains just a single
96  pointer and does no reference counting.
97 
98  __Usage__
99 
100  In the simplest use case, the instantiation type will match the type of object
101  it references, e.g.:
102  @code
103  copyable_unique_ptr<Foo> ptr = make_unique<Foo>(...);
104  @endcode
105  In this case, as long `Foo` is deemed compatible, the behavior will be as
106  expected, i.e., when `ptr` copies, it will contain a reference to a new
107  instance of `Foo`.
108 
109  %copyable_unique_ptr can also be used with polymorphic classes -- a
110  %copyable_unique_ptr, instantiated on a _base_ class, references an
111  instance of a _derived_ class. When copying the object, we would want the copy
112  to likewise contain an instance of the derived class. For example:
113 
114  @code
115  copyable_unique_ptr<Base> cu_ptr = make_unique<Derived>();
116  copyable_unique_ptr<Base> other_cu_ptr = cu_ptr; // Triggers a copy.
117  is_dynamic_castable<Derived>(cu_other_ptr.get()); // Should be true.
118  @endcode
119 
120  This works for well-designed polymorphic classes.
121 
122  @warning Ill-formed polymorphic classes can lead to fatal type slicing of the
123  referenced object, such that the new copy contains an instance of `Base`
124  instead of `Derived`. Some mistakes that would lead to this degenerate
125  behavior:
126  - The `Base` class has a public copy constructor.
127  - The `Base` class's Clone() implementation does not invoke the `Derived`
128  class's implementation of a suitable virtual method.
129 
130  @internal For future developers:
131  - the copyability of a base class does *not* imply anything about the
132  copyability of a derived class. In other words, `copyable_unique_ptr<Base>`
133  can be compilable while `copyable_unique_ptr<Derived>` is not.
134  - Given the pointer `copyable_unique_ptr<Base> ptr(new Derived())`, even if
135  this copies "correctly" (such that the copy contains an instance of
136  `Derived`), this does _not_ imply that `copyable_unique_ptr<Derived>` is
137  compilable.
138 
139  @see is_copyable_unique_ptr_compatible
140  @tparam T The type of the contained object, which *must* be
141  @ref is_copyable_unique_ptr_compatible "compatibly copyable". May
142  be an abstract or concrete type.
143  */
144 // TODO(SeanCurtis-TRI): Consider extending this to add the Deleter as well.
145 template <typename T>
146 class copyable_unique_ptr : public std::unique_ptr<T> {
148  "copyable_unique_ptr can only be used with a 'copyable' class"
149  ", requiring either a public copy constructor or a valid "
150  "clone method of the form: `unique_ptr<T> Clone() const`.");
151 
152  public:
153  /** @name Constructors **/
154  /**@{*/
155 
156  /** Default constructor stores a `nullptr`. No heap allocation is performed.
157  The empty() method will return true when called on a default-constructed
158  %copyable_unique_ptr. */
159  copyable_unique_ptr() noexcept : std::unique_ptr<T>() {}
160 
161  /** Given a pointer to a writable heap-allocated object, take over
162  ownership of that object. No copying occurs. */
163  explicit copyable_unique_ptr(T* ptr) noexcept : std::unique_ptr<T>(ptr) {}
164 
165  /** Copy constructor is deep; the new %copyable_unique_ptr object contains a
166  new copy of the object in the source, created via the source object's
167  copy constructor or `Clone()` method. If the source container is empty this
168  one will be empty also. */
170  : std::unique_ptr<T>(CopyOrNull(cu_ptr.get())) {}
171 
172  /** Copy constructor from a standard `unique_ptr` of _compatible_ type. The
173  copy is deep; the new %copyable_unique_ptr object contains a new copy of the
174  object in the source, created via the source object's copy constructor or
175  `Clone()` method. If the source container is empty this one will be empty
176  also. */
177  template <typename U>
178  explicit copyable_unique_ptr(const std::unique_ptr<U>& u_ptr)
179  : std::unique_ptr<T>(CopyOrNull(u_ptr.get())) {}
180 
181  /** Move constructor is very fast and leaves the source empty. Ownership
182  is transferred from the source to the new %copyable_unique_ptr. If the source
183  was empty this one will be empty also. No heap activity occurs. */
185  : std::unique_ptr<T>(cu_ptr.release()) {}
186 
187  /** Move constructor from a standard `unique_ptr`. The move is very fast and
188  leaves the source empty. Ownership is transferred from the source to the new
189  %copyable_unique_ptr. If the source was empty this one will be empty also. No
190  heap activity occurs. */
191  explicit copyable_unique_ptr(std::unique_ptr<T>&& u_ptr) noexcept
192  : std::unique_ptr<T>(u_ptr.release()) {}
193 
194  /** Move construction from a compatible standard `unique_ptr`. Type `U*` must
195  be implicitly convertible to type `T*`. Ownership is transferred from the
196  source to the new %copyable_unique_ptr. If the source was empty this one will
197  be empty also. No heap activity occurs. */
198  template <typename U>
199  explicit copyable_unique_ptr(std::unique_ptr<U>&& u_ptr) noexcept
200  : std::unique_ptr<T>(u_ptr.release()) {}
201 
202  /**@}*/
203 
204  /** @name Assignment */
205  /**@{*/
206 
207  /** This form of assignment replaces the currently-held object by
208  the given source object and takes over ownership of the source object. The
209  currently-held object (if any) is deleted. */
210  copyable_unique_ptr& operator=(T* ptr) noexcept {
211  std::unique_ptr<T>::reset(ptr);
212  return *this;
213  }
214 
215  /** This form of assignment replaces the currently-held object by a
216  heap-allocated copy of the source object, created using its copy
217  constructor or `Clone()` method. The currently-held object (if any) is
218  deleted. */
219  copyable_unique_ptr & operator=(const T& ref) {
220  std::unique_ptr<T>::reset(CopyOrNull(&ref));
221  return *this;
222  }
223 
224  /** Copy assignment from %copyable_unique_ptr replaces the currently-held
225  object by a copy of the object held in the source container, created using
226  the source object's copy constructor or `Clone()` method. The currently-held
227  object (if any) is deleted. If the source container is empty this one will be
228  empty also after the assignment. Nothing happens if the source and
229  destination are the same container. */
231  return operator=(static_cast<const std::unique_ptr<T>&>(cu_ptr));
232  }
233 
234  /** Copy assignment from a compatible %copyable_unique_ptr replaces the
235  currently-held object by a copy of the object held in the source container,
236  created using the source object's copy constructor or `Clone()` method. The
237  currently-held object (if any) is deleted. If the source container is empty
238  this one will be empty also after the assignment. Nothing happens if the
239  source and destination are the same container. */
240  template <typename U>
242  return operator=(static_cast<const std::unique_ptr<U>&>(cu_ptr));
243  }
244 
245  /** Copy assignment from a standard `unique_ptr` replaces the
246  currently-held object by a copy of the object held in the source container,
247  created using the source object's copy constructor or `Clone()` method. The
248  currently-held object (if any) is deleted. If the source container is empty
249  this one will be empty also after the assignment. Nothing happens if the
250  source and destination are the same container. */
251  copyable_unique_ptr& operator=(const std::unique_ptr<T>& src) {
252  if (&src != this) {
253  // can't be same ptr unless null
254  DRAKE_DEMAND((get() != src.get()) || !get());
255  std::unique_ptr<T>::reset(CopyOrNull(src.get()));
256  }
257  return *this;
258  }
259 
260  /** Copy assignment from a compatible standard `unique_ptr` replaces the
261  currently-held object by a copy of the object held in the source container,
262  created using the source object's copy constructor or `Clone()` method. The
263  currently-held object (if any) is deleted. If the source container is empty
264  this one will be empty also after the assignment. Nothing happens if the
265  source and destination are the same container. */
266  template <typename U>
267  copyable_unique_ptr& operator=(const std::unique_ptr<U>& u_ptr) {
268  // can't be same ptr unless null
269  DRAKE_DEMAND((get() != u_ptr.get()) || !get());
270  std::unique_ptr<T>::reset(CopyOrNull(u_ptr.get()));
271  return *this;
272  }
273 
274  /** Move assignment replaces the currently-held object by the source object,
275  leaving the source empty. The currently-held object (if any) is deleted.
276  The instance is _not_ copied. Nothing happens if the source and destination
277  are the same containers. */
279  std::unique_ptr<T>::reset(cu_ptr.release());
280  return *this;
281  }
282 
283  /** Move assignment replaces the currently-held object by the compatible
284  source object, leaving the source empty. The currently-held object (if any)
285  is deleted. The instance is _not_ copied. Nothing happens if the source and
286  destination are the same containers. */
287  template <typename U>
289  std::unique_ptr<T>::reset(cu_ptr.release());
290  return *this;
291  }
292 
293  /** Move assignment replaces the currently-held object by the source object,
294  leaving the source empty. The currently-held object (if any) is deleted.
295  The instance is _not_ copied. Nothing happens if the source and destination
296  are the same containers. */
297  copyable_unique_ptr& operator=(std::unique_ptr<T>&& u_ptr) noexcept {
298  std::unique_ptr<T>::reset(u_ptr.release());
299  return *this;
300  }
301 
302  /** Move assignment replaces the currently-held object by the compatible
303  source object, leaving the source empty. The currently-held object (if
304  any) is deleted. The instance is _not_ copied. Nothing happens if the source
305  and destination are the same containers. */
306  template <typename U>
307  copyable_unique_ptr& operator=(std::unique_ptr<U>&& u_ptr) noexcept {
308  std::unique_ptr<T>::reset(u_ptr.release());
309  return *this;
310  }
311 
312  /**@}*/
313 
314  /** @name Observers */
315  /**@{*/
316 
317  /** Return true if this container is empty, which is the state the container
318  is in immediately after default construction and various other
319  operations. */
320  bool empty() const noexcept { return !(*this); }
321 
322  /** Return a const pointer to the contained object if any, or `nullptr`.
323  Note that this is different than `%get()` for the standard smart pointers
324  like `std::unique_ptr` which return a writable pointer. Use get_mutable()
325  here for that purpose. */
326  const T* get() const noexcept { return std::unique_ptr<T>::get(); }
327 
328  /** Return a writable pointer to the contained object if any, or `nullptr`.
329  Note that you need write access to this container in order to get write
330  access to the object it contains.
331 
332  @warning If %copyable_unique_ptr is instantiated on a const template
333  parameter (e.g., `copyable_unique_ptr<const Foo>`), then get_mutable()
334  returns a const pointer. */
335  T* get_mutable() noexcept { return std::unique_ptr<T>::get(); }
336 
337  /**@}*/
338 
339  private:
340  // Selects Clone iff there is no copy constructor and the Clone method is of
341  // the expected form.
342  template <typename U>
343  static typename std::enable_if<
345  CopyOrNullHelper(const U* ptr, int) {
346  return ptr->Clone().release();
347  }
348 
349  // Default to copy constructor if present.
350  template <typename U>
351  static
352  U* CopyOrNullHelper(const U* ptr, ...) {
353  return new U(*ptr);
354  }
355 
356  // If src is non-null, clone it; otherwise return nullptr.
357  static T* CopyOrNull(const T *ptr) {
358  return ptr ? CopyOrNullHelper(ptr, 1) : nullptr;
359  }
360 };
361 
362 /** Output the system-dependent representation of the pointer contained
363  in a copyable_unique_ptr object. This is equivalent to `os << p.get();`.
364  @relates copyable_unique_ptr */
365 template <class charT, class traits, class T>
366 inline std::basic_ostream<charT, traits>& operator<<(
367  std::basic_ostream<charT, traits>& os,
368  const copyable_unique_ptr<T>& cu_ptr) {
369  os << cu_ptr.get();
370  return os;
371 }
372 
373 } // namespace drake
copyable_unique_ptr_detail::is_copyable_unique_ptr_compatible_helper< T, void > is_copyable_unique_ptr_compatible
Test for determining if an arbitrary class is compatible with the copyable_unique_ptr.
Definition: copyable_unique_ptr.h:72
is_cloneable_detail::is_cloneable_helper< T, void > is_cloneable
Definition: is_cloneable.h:78
YAML::Node get(const YAML::Node &parent, const std::string &key)
Definition: yaml_util.cc:61
copyable_unique_ptr & operator=(std::unique_ptr< T > &&u_ptr) noexcept
Move assignment replaces the currently-held object by the source object, leaving the source empty...
Definition: copyable_unique_ptr.h:297
copyable_unique_ptr() noexcept
Default constructor stores a nullptr.
Definition: copyable_unique_ptr.h:159
copyable_unique_ptr(T *ptr) noexcept
Given a pointer to a writable heap-allocated object, take over ownership of that object.
Definition: copyable_unique_ptr.h:163
Definition: automotive_demo.cc:88
copyable_unique_ptr & operator=(T *ptr) noexcept
This form of assignment replaces the currently-held object by the given source object and takes over ...
Definition: copyable_unique_ptr.h:210
STL namespace.
copyable_unique_ptr(std::unique_ptr< U > &&u_ptr) noexcept
Move construction from a compatible standard unique_ptr.
Definition: copyable_unique_ptr.h:199
copyable_unique_ptr & operator=(const std::unique_ptr< T > &src)
Copy assignment from a standard unique_ptr replaces the currently-held object by a copy of the object...
Definition: copyable_unique_ptr.h:251
copyable_unique_ptr & operator=(const copyable_unique_ptr< U > &cu_ptr)
Copy assignment from a compatible copyable_unique_ptr replaces the currently-held object by a copy of...
Definition: copyable_unique_ptr.h:241
int value
Definition: copyable_unique_ptr_test.cc:61
Provides Drake&#39;s assertion implementation.
std::ostream & operator<<(std::ostream &out, const LaneEnd::Which &which_end)
Streams a string representation of which_end into out.
Definition: lane_data.cc:11
#define DRAKE_DEMAND(condition)
Evaluates condition and iff the value is false will trigger an assertion failure with a message showi...
Definition: drake_assert.h:45
copyable_unique_ptr & operator=(const copyable_unique_ptr &cu_ptr)
Copy assignment from copyable_unique_ptr replaces the currently-held object by a copy of the object h...
Definition: copyable_unique_ptr.h:230
copyable_unique_ptr & operator=(copyable_unique_ptr &&cu_ptr) noexcept
Move assignment replaces the currently-held object by the source object, leaving the source empty...
Definition: copyable_unique_ptr.h:278
copyable_unique_ptr(copyable_unique_ptr &&cu_ptr) noexcept
Move constructor is very fast and leaves the source empty.
Definition: copyable_unique_ptr.h:184
copyable_unique_ptr & operator=(const T &ref)
This form of assignment replaces the currently-held object by a heap-allocated copy of the source obj...
Definition: copyable_unique_ptr.h:219
copyable_unique_ptr & operator=(std::unique_ptr< U > &&u_ptr) noexcept
Move assignment replaces the currently-held object by the compatible source object, leaving the source empty.
Definition: copyable_unique_ptr.h:307
const T * get() const noexcept
Return a const pointer to the contained object if any, or nullptr.
Definition: copyable_unique_ptr.h:326
copyable_unique_ptr & operator=(const std::unique_ptr< U > &u_ptr)
Copy assignment from a compatible standard unique_ptr replaces the currently-held object by a copy of...
Definition: copyable_unique_ptr.h:267
bool empty() const noexcept
Return true if this container is empty, which is the state the container is in immediately after defa...
Definition: copyable_unique_ptr.h:320
copyable_unique_ptr(std::unique_ptr< T > &&u_ptr) noexcept
Move constructor from a standard unique_ptr.
Definition: copyable_unique_ptr.h:191
T * get_mutable() noexcept
Return a writable pointer to the contained object if any, or nullptr.
Definition: copyable_unique_ptr.h:335
copyable_unique_ptr(const std::unique_ptr< U > &u_ptr)
Copy constructor from a standard unique_ptr of compatible type.
Definition: copyable_unique_ptr.h:178
copyable_unique_ptr(const copyable_unique_ptr &cu_ptr)
Copy constructor is deep; the new copyable_unique_ptr object contains a new copy of the object in the...
Definition: copyable_unique_ptr.h:169
copyable_unique_ptr & operator=(copyable_unique_ptr< U > &&cu_ptr) noexcept
Move assignment replaces the currently-held object by the compatible source object, leaving the source empty.
Definition: copyable_unique_ptr.h:288
A smart pointer with deep copy semantics.
Definition: copyable_unique_ptr.h:146