Drake
is_cloneable.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <memory>
4 #include <type_traits>
5 
6 namespace drake {
7 
8 /** @cond */
9 
10 namespace is_cloneable_detail {
11 
12 // Default case; assumes that a class is *not* cloneable.
13 template <typename T, class>
14 struct is_cloneable_helper : std::false_type {};
15 
16 // Special sauce for SFINAE. Only compiles if it can finds the method
17 // `unique_ptr<T> T::Clone() const`. If this exists, the is_cloneable implicitly
18 // prefers this overload over the default overload.
19 template <typename T>
20 struct is_cloneable_helper<
21  T,
22  typename std::enable_if<std::is_same<
23  decltype(std::declval<const T>().Clone().release()),
24  typename std::remove_const<T>::type*>::value>::type>
25  : std::true_type {};
26 
27 } // namespace is_cloneable_detail
28 
29 /** @endcond */
30 
31 /**
32  @anchor is_cloneable_doc
33  Provides method for determining at run time if a class is "cloneable".
34 
35  __Usage__
36 
37  This gets used like `type_traits` functions (e.g., `is_copy_constructible`,
38  `is_same`, etc.) To determine if a class is cloneable simply invoke:
39 
40  @code
41  bool value = drake::is_cloneable<Foo>::value;
42  @endcode
43 
44  If `Foo` is cloneable, it will evalute to true. It can also be used in
45  compile-time tests (e.g., SFINAE and `static_assert`s):
46 
47  @code
48  static_assert(is_cloneable<Foo>::value, "This method requires its classes to "
49  "be cloneable.");
50  @endcode
51 
52  __Definition of "cloneability"__
53 
54  To be cloneable, the class `Foo` must have a public method of the form:
55 
56  @code
57  unique_ptr<Foo> Foo::Clone() const;
58  @endcode
59 
60  The pointer contained in the returned `unique_ptr` must point to a
61  heap-allocated deep copy of the _concrete_ object. This test can confirm the
62  proper signature, but cannot confirm the heap-allocated deep copy. A Clone()
63  method that doesn't return such a copy of the _concrete_ object should be
64  considered a malformed function.
65 
66  @warning It is important to note, that a `Clone()` method that returns a
67  `unique_ptr` to a _super_ class is _not_ sufficient to be cloneable. In other
68  words the presence of:
69  @code
70  unique_ptr<Base> Derived::Clone() const;
71  @endcode
72  will not make the `Derived` class cloneable.
73 
74  @tparam T The class to test for cloneability.
75  */
76 template <typename T>
77 using is_cloneable =
78  is_cloneable_detail::is_cloneable_helper<T, void>;
79 
80 } // namespace drake
is_cloneable_detail::is_cloneable_helper< T, void > is_cloneable
Definition: is_cloneable.h:78
Definition: automotive_demo.cc:88
STL namespace.