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 
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
69 template <typename T>
71  copyable_unique_ptr_detail::is_copyable_unique_ptr_compatible_helper<T,
72  void>;
73 
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:
159  copyable_unique_ptr() noexcept : std::unique_ptr<T>() {}
160 
163  explicit copyable_unique_ptr(T* ptr) noexcept : std::unique_ptr<T>(ptr) {}
164 
170  : std::unique_ptr<T>(CopyOrNull(cu_ptr.get())) {}
171 
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 
185  : std::unique_ptr<T>(cu_ptr.release()) {}
186 
191  explicit copyable_unique_ptr(std::unique_ptr<T>&& u_ptr) noexcept
192  : std::unique_ptr<T>(u_ptr.release()) {}
193 
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 
210  copyable_unique_ptr& operator=(T* ptr) noexcept {
211  std::unique_ptr<T>::reset(ptr);
212  return *this;
213  }
214 
219  copyable_unique_ptr & operator=(const T& ref) {
220  std::unique_ptr<T>::reset(CopyOrNull(&ref));
221  return *this;
222  }
223 
231  return operator=(static_cast<const std::unique_ptr<T>&>(cu_ptr));
232  }
233 
240  template <typename U>
242  return operator=(static_cast<const std::unique_ptr<U>&>(cu_ptr));
243  }
244 
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 
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 
279  std::unique_ptr<T>::reset(cu_ptr.release());
280  return *this;
281  }
282 
287  template <typename U>
289  std::unique_ptr<T>::reset(cu_ptr.release());
290  return *this;
291  }
292 
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 
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 
320  bool empty() const noexcept { return !(*this); }
321 
326  const T* get() const noexcept { return std::unique_ptr<T>::get(); }
327 
335  T* get_mutable() noexcept { return std::unique_ptr<T>::get(); }
336 
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 
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: yamlUtil.cpp:56
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:9
#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:47
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