CASM  1.1.0
A Clusters Approach to Statistical Mechanics
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 <iostream>
5 #include <memory>
6 #include <utility>
7 
9 
12 #define ABSTRACT_CLONEABLE(T) \
13  public: \
14  virtual ~T() {} \
15  \
16  std::unique_ptr<T> clone() const { \
17  return std::unique_ptr<T>(this->_clone()); \
18  } \
19  std::unique_ptr<T> move() { return std::unique_ptr<T>(this->_move()); } \
20  \
21  private: \
22  virtual T *_clone() const = 0; \
23  virtual T *_move() = 0; \
24  \
25  public:
26 
29 #define ABSTRACT_CLONEABLE_DERIVED(T) \
30  public: \
31  virtual ~T() {} \
32  \
33  std::unique_ptr<T> clone() const { \
34  return std::unique_ptr<T>(this->_clone()); \
35  } \
36  std::unique_ptr<T> move() { return std::unique_ptr<T>(this->_move()); } \
37  \
38  private: \
39  virtual T *_clone() const override = 0; \
40  virtual T *_move() override = 0; \
41  \
42  public:
43 
46 #define CLONEABLE(T) \
47  public: \
48  virtual ~T() {} \
49  \
50  std::unique_ptr<T> clone() const { \
51  return std::unique_ptr<T>(this->_clone()); \
52  } \
53  std::unique_ptr<T> move() { return std::unique_ptr<T>(this->_move()); } \
54  \
55  private: \
56  virtual T *_clone() const override { return new T(*this); } \
57  virtual T *_move() override { return new T(std::move(*this)); } \
58  \
59  public:
60 
63 #define CLONEABLE_NEEDS_DESTRUCTOR_DEF(T) \
64  public: \
65  virtual ~T(); \
66  \
67  std::unique_ptr<T> clone() const { \
68  return std::unique_ptr<T>(this->_clone()); \
69  } \
70  std::unique_ptr<T> move() { return std::unique_ptr<T>(this->_move()); } \
71  \
72  private: \
73  virtual T *_clone() const override { return new T(*this); } \
74  virtual T *_move() override { return new T(std::move(*this)); } \
75  \
76  public:
77 
79 namespace notstd {
80 
82 template <typename T, typename... Args>
83 std::unique_ptr<T> make_unique(Args &&... args) {
84  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
85 }
86 
88 class Cloneable {
89  public:
90  virtual ~Cloneable() {}
91 
92  std::unique_ptr<Cloneable> clone() const {
93  return std::unique_ptr<Cloneable>(this->_clone());
94  }
95  std::unique_ptr<Cloneable> move() {
96  return std::unique_ptr<Cloneable>(this->_move());
97  }
98 
99  private:
100  virtual Cloneable *_clone() const = 0;
101  virtual Cloneable *_move() = 0;
102 };
103 
104 template <typename Type>
105 class cloneable_ptr;
106 
108 template <typename T, typename... Args>
110  return cloneable_ptr<T>(new T(std::forward<Args>(args)...));
111 }
112 
115 template <typename T, typename = void>
116 struct has_clone : std::false_type {};
117 
120 template <typename T>
121 struct has_clone<T, void_t<decltype(&T::clone)> > : std::true_type {};
122 
123 template <typename T,
124  typename std::enable_if<!has_clone<T>::value, void>::type * = nullptr>
125 std::unique_ptr<T> clone(const T &obj);
126 
127 template <typename T,
128  typename std::enable_if<has_clone<T>::value, void>::type * = nullptr>
129 std::unique_ptr<T> clone(const T &obj);
130 
133 template <typename T, typename = void>
134 struct has_move : std::false_type {};
135 
138 template <typename T>
139 struct has_move<T, void_t<decltype(&T::move)> > : std::true_type {};
140 
142 template <typename T,
143  typename std::enable_if<!has_move<T>::value, void>::type * = nullptr>
144 std::unique_ptr<T> clone_move(T &&obj);
145 
147 template <typename T,
148  typename std::enable_if<has_move<T>::value, void>::type * = nullptr>
149 std::unique_ptr<T> clone_move(T &&obj);
150 
162 template <typename Type>
164  public:
165  typedef Type element_type;
166  typedef Type *pointer;
167  typedef Type &reference;
168 
171 
173  explicit cloneable_ptr(pointer ptr);
174 
177 
179  template <typename U>
181 
184 
186  template <typename U>
188 
190  template <typename U>
191  cloneable_ptr(const std::unique_ptr<U> &other);
192 
194  template <typename U>
195  cloneable_ptr(std::unique_ptr<U> &&other);
196 
198 
201 
203  template <typename U>
205 
207  template <typename U>
208  cloneable_ptr &operator=(const std::unique_ptr<U> &other);
209 
211  template <typename U>
212  cloneable_ptr &operator=(std::unique_ptr<U> &&other);
213 
215 
217 
219  void reset();
220 
222  std::unique_ptr<Type> &unique();
223 
225  const std::unique_ptr<Type> &unique() const;
226 
228  explicit operator bool() const;
229 
230  private:
231  std::unique_ptr<Type> m_unique;
232 };
233 
234 template <typename Type>
236 
237 template <typename Type>
238 bool operator<(const cloneable_ptr<Type> &A, const cloneable_ptr<Type> &B);
239 
240 template <typename Type>
241 bool operator==(const cloneable_ptr<Type> &A, const cloneable_ptr<Type> &B);
242 
243 template <typename Type>
244 bool operator!=(const cloneable_ptr<Type> &A, const cloneable_ptr<Type> &B);
245 
246 template <typename Type>
247 bool operator==(std::nullptr_t, const cloneable_ptr<Type> &B);
248 
249 template <typename Type>
250 bool operator!=(std::nullptr_t, const cloneable_ptr<Type> &B);
251 
252 template <typename Type>
253 bool operator==(const cloneable_ptr<Type> &A, std::nullptr_t);
254 
255 template <typename Type>
256 bool operator!=(const cloneable_ptr<Type> &A, std::nullptr_t);
257 
258 // --- Immplementation ---
259 
260 template <typename T,
261  typename std::enable_if<!has_clone<T>::value, void>::type *>
262 std::unique_ptr<T> clone(const T &obj) {
263  return std::unique_ptr<T>(new T(obj));
264 }
265 
266 template <typename T,
267  typename std::enable_if<has_clone<T>::value, void>::type *>
268 std::unique_ptr<T> clone(const T &obj) {
269  return obj.clone();
270 }
271 
277 template <typename T,
278  typename std::enable_if<!has_move<T>::value, void>::type *>
279 std::unique_ptr<T> clone_move(T &&obj) {
280  return clone(std::move(obj));
281 }
282 
288 template <typename T, typename std::enable_if<has_move<T>::value, void>::type *>
289 std::unique_ptr<T> clone_move(T &&obj) {
290  return obj.move();
291 }
292 
294 template <typename Type>
296 
298 template <typename Type>
300  if (other) {
301  m_unique = std::move(clone(*other));
302  }
303 }
304 
306 template <typename Type>
307 template <typename U>
309  if (other) {
310  m_unique = std::move(clone(*other));
311  }
312 }
313 
315 template <typename Type>
317  : m_unique(std::move(other.unique())) {}
318 
320 template <typename Type>
321 template <typename U>
323  : m_unique(std::move(other.unique())) {}
324 
326 template <typename Type>
327 template <typename U>
328 cloneable_ptr<Type>::cloneable_ptr(const std::unique_ptr<U> &other)
329  : m_unique() {
330  if (other) {
331  m_unique = std::move(clone(*other));
332  }
333 }
334 
336 template <typename Type>
337 template <typename U>
338 cloneable_ptr<Type>::cloneable_ptr(std::unique_ptr<U> &&other)
339  : m_unique(std::move(other)) {}
340 
341 template <typename Type>
343 
345 template <typename Type>
347  swap(*this, other);
348  return *this;
349 }
350 
352 template <typename Type>
353 template <typename U>
355  unique() = std::move(other.unique());
356  return *this;
357 }
358 
360 template <typename Type>
361 template <typename U>
363  const std::unique_ptr<U> &other) {
364  if (other) {
365  unique() = clone(*other);
366  } else {
367  unique().reset();
368  }
369  return *this;
370 }
371 
373 template <typename Type>
374 template <typename U>
376  std::unique_ptr<U> &&other) {
377  unique() = std::move(other);
378  return *this;
379 }
380 
381 template <typename Type>
383  return *m_unique;
384 }
385 
386 template <typename Type>
388  return &(this->operator*());
389 }
390 
392 template <typename Type>
394  return m_unique.reset();
395 }
396 
398 template <typename Type>
399 std::unique_ptr<Type> &cloneable_ptr<Type>::unique() {
400  return m_unique;
401 }
402 
404 template <typename Type>
405 const std::unique_ptr<Type> &cloneable_ptr<Type>::unique() const {
406  return m_unique;
407 }
408 
410 template <typename Type>
412  return static_cast<bool>(m_unique);
413 }
414 
415 template <typename Type>
417  A.unique().swap(B.unique());
418 }
419 
420 template <typename Type>
422  return A.unique() < B.unique();
423 }
424 
425 template <typename Type>
427  return A.unique() == B.unique();
428 }
429 
430 template <typename Type>
432  return A.unique() != B.unique();
433 }
434 
435 template <typename Type>
436 bool operator==(std::nullptr_t, const cloneable_ptr<Type> &B) {
437  return B.unique() == nullptr;
438 }
439 
440 template <typename Type>
441 bool operator!=(std::nullptr_t, const cloneable_ptr<Type> &B) {
442  return B.unique() != nullptr;
443 }
444 
445 template <typename Type>
446 bool operator==(const cloneable_ptr<Type> &A, std::nullptr_t) {
447  return A.unique() == nullptr;
448 }
449 
450 template <typename Type>
451 bool operator!=(const cloneable_ptr<Type> &A, std::nullptr_t) {
452  return A.unique() != nullptr;
453 }
454 
455 } // namespace notstd
456 
457 #endif
Base class for cloning.
std::unique_ptr< Cloneable > clone() const
virtual ~Cloneable()
virtual Cloneable * _clone() const =0
virtual Cloneable * _move()=0
std::unique_ptr< Cloneable > move()
A 'cloneable_ptr' can be used in place of 'unique_ptr'.
cloneable_ptr(pointer ptr)
Construct by taking ownership of ptr.
cloneable_ptr(const cloneable_ptr< U > &other)
Construct by cloning other.
cloneable_ptr(cloneable_ptr< U > &&other)
Construct by moving other.
cloneable_ptr & operator=(cloneable_ptr< U > &&other)
Assignment via move.
const std::unique_ptr< Type > & unique() const
const Access contained unique_ptr
std::unique_ptr< Type > m_unique
cloneable_ptr(cloneable_ptr &&other)
Construct by moving other.
cloneable_ptr(const cloneable_ptr &other)
Construct by cloning other.
std::unique_ptr< Type > & unique()
Access contained unique_ptr.
pointer operator->() const
cloneable_ptr()
Default constructor.
void reset()
Reset contained unique_ptr.
cloneable_ptr(std::unique_ptr< U > &&other)
Construct by moving.
cloneable_ptr & operator=(cloneable_ptr other)
Assignment via copy-swap.
cloneable_ptr(const std::unique_ptr< U > &other)
Construct by cloning other.
reference operator*() const
cloneable_ptr & operator=(std::unique_ptr< U > &&other)
Assignment via move.
cloneable_ptr & operator=(const std::unique_ptr< U > &other)
Assignment via clone.
BasisSet operator*(const SymOp &LHS, const BasisSet &RHS)
Definition: BasisSet.cc:1408
Non-std smart pointer classes and functions.
std::unique_ptr< T > clone(const T &obj)
bool operator!=(const cloneable_ptr< Type > &A, const cloneable_ptr< Type > &B)
cloneable_ptr< T > make_cloneable(Args &&... args)
make a cloneable_ptr<T> via T(Args... args)
typename make_void< Ts... >::type void_t
Alias for void, to help SFINAE work.
Definition: type_traits.hh:16
bool operator==(const cloneable_ptr< Type > &A, const cloneable_ptr< Type > &B)
bool operator<(const cloneable_ptr< Type > &A, const cloneable_ptr< Type > &B)
std::unique_ptr< T > clone_move(T &&obj)
Construct std::unique_ptr<T> from rvalue reference.
std::unique_ptr< T > make_unique(Args &&... args)
c++17 does not include 'make_unique'
void swap(cloneable_ptr< Type > &A, cloneable_ptr< Type > &B)
Definition: stream_io.hh:24
Base type inherits from std::false_type if T does not have clone method.
Base type inherits from std::false_type if T does not have move method.