CASM
AClustersApproachtoStatisticalMechanics
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
cloneable_ptr.hh
Go to the documentation of this file.
1 #ifndef CASM_cloneable_ptr_HH
2 #define CASM_cloneable_ptr_HH
3 
4 #include <memory>
5 #include <iostream>
6 
7 #include "casm/misc/CASM_TMP.hh"
8 
10 namespace notstd {
11 
13  template<typename T, typename ...Args>
14  std::unique_ptr<T> make_unique(Args &&...args) {
15  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
16  }
17 
18  class Cloneable {
19  public:
20  std::unique_ptr<Cloneable> clone() const {
21  return std::unique_ptr<Cloneable>(this->_clone());
22  }
23  private:
24  virtual Cloneable *_clone() const = 0;
25  };
26 
27  template<typename Type>
29 
31  template<typename T, typename ...Args>
32  cloneable_ptr<T> make_cloneable(Args &&...args) {
33  return cloneable_ptr<T>(new T(std::forward<Args>(args)...));
34  }
35 
37  template <typename T, typename = void>
38  struct has_clone : std::false_type { };
39 
41  template <typename T>
42 struct has_clone<T, CASM::CASM_TMP::void_t<decltype(std::declval<T &>().clone())> > : std::true_type { };
43 
44 
45  template<typename T>
46  std::unique_ptr<T> clone(const T &obj, typename std::enable_if<has_clone<T>::value, T>::type * = nullptr) {
47  return obj.clone();
48  }
49 
50  template<typename T>
51  std::unique_ptr<T> clone(const T &obj, typename std::enable_if < !has_clone<T>::value, T >::type * = nullptr) {
52  return std::unique_ptr<T>(new T(obj));
53  }
54 
55 
65  template<typename Type>
66  class cloneable_ptr {
67 
68  public:
69 
70  typedef Type element_type;
71  typedef Type *pointer;
72  typedef Type &reference;
73 
76 
78  explicit cloneable_ptr(pointer ptr) :
79  m_unique(ptr) {}
80 
82  explicit cloneable_ptr(const Type &obj) :
83  m_unique(clone(obj)) {}
84 
85 
87  cloneable_ptr(const cloneable_ptr &other) :
88  m_unique() {
89  if(other) {
90  m_unique = std::move(clone(*other));
91  }
92  }
93 
95  template<typename U>
97  m_unique() {
98  if(other) {
99  m_unique = std::move(clone(*other));
100  }
101  }
102 
104  template<typename U>
106  m_unique(std::move(other.unique())) {}
107 
108 
110  template<typename U>
111  cloneable_ptr(const std::unique_ptr<U> &other) :
112  m_unique() {
113  if(other) {
114  m_unique = std::move(clone(*other));
115  }
116  }
117 
119  template<typename U>
120  cloneable_ptr(std::unique_ptr<U> &&other) :
121  m_unique(std::move(other)) {}
122 
123 
126  swap(*this, other);
127  return *this;
128  }
129 
131  template<typename U>
133  unique() = std::move(other.unique());
134  return *this;
135  }
136 
137 
139  template<typename U>
140  cloneable_ptr &operator=(const std::unique_ptr<U> &other) {
141  if(other) {
142  unique() = clone(*other);
143  }
144  else {
145  unique().reset();
146  }
147  return *this;
148  }
149 
151  template<typename U>
152  cloneable_ptr &operator=(std::unique_ptr<U> && other) {
153  unique() = std::move(other);
154  return *this;
155  }
156 
157 
158  reference operator*() const {
159  return *m_unique;
160  }
161 
162  pointer operator->() const {
163  return &(this->operator*());
164  }
165 
167  void reset() {
168  return m_unique.reset();
169  }
170 
172  std::unique_ptr<Type> &unique() {
173  return m_unique;
174  }
175 
177  const std::unique_ptr<Type> &unique() const {
178  return m_unique;
179  }
180 
182  explicit operator bool() const {
183  return static_cast<bool>(m_unique);
184  }
185 
186  private:
187 
188  std::unique_ptr<Type> m_unique;
189 
190  };
191 
192  template<typename Type>
194  A.unique().swap(B.unique());
195  }
196 
197  template<typename Type>
198  bool operator<(const cloneable_ptr<Type> &A, const cloneable_ptr<Type> &B) {
199  return A.unique() < B.unique();
200  }
201 
202  template<typename Type>
204  return A.unique() == B.unique();
205  }
206 
207  template<typename Type>
209  return A.unique() != B.unique();
210  }
211 }
212 
213 #endif
void swap(cloneable_ptr< Type > &A, cloneable_ptr< Type > &B)
cloneable_ptr(const Type &obj)
Construct by cloning obj.
std::unique_ptr< T > make_unique(Args &&...args)
c++11 does not include 'make_unique'
virtual Cloneable * _clone() const =0
cloneable_ptr & operator=(cloneable_ptr other)
Assignment via copy-swap.
cloneable_ptr(pointer ptr)
Construct by taking ownership of ptr.
reference operator*() const
cloneable_ptr(cloneable_ptr< U > &&other)
Construct by moving other.
cloneable_ptr(const std::unique_ptr< U > &other)
Construct by cloning other.
cloneable_ptr()
Default constructor.
typename make_void< Ts...>::type void_t
Alias for void, to help SFINAE work.
Definition: CASM_TMP.hh:31
Base type inherits from std::false_type if T does not have clone method.
cloneable_ptr & operator=(cloneable_ptr< U > &&other)
Assignment via move.
Main CASM namespace.
Definition: complete.cpp:8
bool operator!=(const cloneable_ptr< Type > &A, const cloneable_ptr< Type > &B)
cloneable_ptr(std::unique_ptr< U > &&other)
Construct by moving.
pointer operator->() const
cloneable_ptr< T > make_cloneable(Args &&...args)
make a cloneable_ptr via T(Args... args)
const std::unique_ptr< Type > & unique() const
const Access contained unique_ptr
void reset()
Reset contained unique_ptr.
std::unique_ptr< T > clone(const T &obj, typename std::enable_if< has_clone< T >::value, T >::type *=nullptr)
bool operator==(const cloneable_ptr< Type > &A, const cloneable_ptr< Type > &B)
Non-std smart pointer classes and functions.
std::unique_ptr< Type > m_unique
cloneable_ptr & operator=(std::unique_ptr< U > &&other)
Assignment via move.
std::unique_ptr< Type > & unique()
Access contained unique_ptr.
cloneable_ptr & operator=(const std::unique_ptr< U > &other)
Assignment via clone.
A 'cloneable_ptr' can be used in place of 'unique_ptr'.
std::unique_ptr< Cloneable > clone() const
cloneable_ptr(const cloneable_ptr< U > &other)
Construct by cloning other.
cloneable_ptr(const cloneable_ptr &other)
Construct by cloning other.