1 
2 /**
3  *    Copyright (C) 2018-present MongoDB, Inc.
4  *
5  *    This program is free software: you can redistribute it and/or modify
6  *    it under the terms of the Server Side Public License, version 1,
7  *    as published by MongoDB, Inc.
8  *
9  *    This program is distributed in the hope that it will be useful,
10  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *    Server Side Public License for more details.
13  *
14  *    You should have received a copy of the Server Side Public License
15  *    along with this program. If not, see
16  *    <http://www.mongodb.com/licensing/server-side-public-license>.
17  *
18  *    As a special exception, the copyright holders give permission to link the
19  *    code of portions of this program with the OpenSSL library under certain
20  *    conditions as described in each individual source file and distribute
21  *    linked combinations including the program with the OpenSSL library. You
22  *    must comply with the Server Side Public License in all respects for
23  *    all of the code used other than as permitted herein. If you modify file(s)
24  *    with this exception, you may extend this exception to your version of the
25  *    file(s), but you are not obligated to do so. If you do not wish to do so,
26  *    delete this exception statement from your version. If you delete this
27  *    exception statement from all source files in the program, then also delete
28  *    it in the license file.
29  */
30 
31 #pragma once
32 
33 #include <cstddef>
34 #include <memory>
35 #include <tuple>
36 #include <type_traits>
37 
38 namespace mongo {
39 namespace clonable_ptr_detail {
40 // This is the default `CloneFactory` conforming to `mongo::concept::CloneFactory` for
41 // `clonable_ptr`.
42 template <typename Clonable>
43 struct CloneFactory {
44     auto operator()(const Clonable& c) const -> decltype(c.clone()) {
45         return c.clone();
46     }
47 };
48 
49 // TODO: Move some of these traits detection structs to a template metaprogramming header.
50 template <typename T>
51 struct detect_clone_factory_type_member_impl {
52     struct Fallback {
53         struct clone_factory_type {};
54     };
55 
56     struct Derived : T, Fallback {};
57 
58     using Yes = char[2];
59     using No = char[1];
60 
61     template <typename U>
62     static No& test(typename U::clone_factory_type*);
63 
64     template <typename U>
65     static Yes& test(U*);
66 
67     static constexpr bool value = sizeof(test<Derived>(0)) == sizeof(Yes);
68 
69     using type = typename std::integral_constant<bool, value>::type;
70 };
71 
72 template <typename T>
73 struct detect_clone_factory_type_member : std::conditional<std::is_class<T>::value,
74                                                            detect_clone_factory_type_member_impl<T>,
75                                                            std::false_type>::type {};
76 
77 template <typename T, bool has_clone_factory_member = detect_clone_factory_type_member<T>::value>
78 struct clonable_traits_impl;
79 
80 template <typename T>
81 struct clonable_traits_impl<T, false> {
82     using clone_factory_type = CloneFactory<T>;
83 };
84 
85 template <typename T>
86 struct clonable_traits_impl<T, true> {
87     using clone_factory_type = typename T::clone_factory_type;
88 };
89 }  // namespace clonable_ptr_detail
90 
91 /**
92  * The 'clonable_traits' class is a specializable traits class for clonable-like types.  By
93  * specializing this traits class for a type it is possible to change the global default
94  * `CloneFactory` type for a specific type.  Types which conform to `mongo::concept::Clonable`
95  * will get a default `CloneFactory` type whch invokes their specific `Clonable::clone` function.  A
96  * specialization can be used to make a type use a different clone factory function.  A type `T` may
97  * specify `T::clone_factory_type` instead of specializing this traits type.
98  */
99 template <typename T>
100 struct clonable_traits : clonable_ptr_detail::clonable_traits_impl<T> {};
101 
102 /**
103  * The `clonable_ptr` represents a value-like type held at a distance.  The `clonable_ptr` class is
104  * a smart-pointer type which functions like a `std::unique_ptr` with the added ability to create
105  * new copies of the pointee on copy construction.  The default CloneFactory assumes that `T` is a
106  * type which models the Concept `mongo::concept::Clonable`.  The supplied type may supply an
107  * alternative default `CloneFactory` type by either of two means:
108  *
109  *  * `T` may define a member `T::clone_factory_type` which conforms to
110  *    `mongo::concept::CloneFactory`
111  *  * `T` may have an accompanying specialization of `mongo::clonable_traits< T >` which
112  *    defines `clonable_factory_type`.
113  *
114  * NOTE: The `CloneFactory` type is permitted to be stateful, but must be copy constructible and
115  * copy assignable.
116  * NOTE: The `CloneFactory` member does NOT participate in value comparisons for a `clonable_ptr`,
117  * even when it has state.
118  *
119  * `T`: The type of the object being managed.
120  * `CloneFactory`: A type which models the Concept `mongo::concept::CloneFactory`.
121  * `UniquePtr`: A type which models the Concept `mongo::concept::UniquePtr`
122  */
123 template <typename T,
124           typename CloneFactory = typename clonable_traits<T>::clone_factory_type,
125           template <typename, typename...> class UniquePtr = std::unique_ptr>
126 class clonable_ptr {
127 private:
128     // `std::tuple` is used to avoid allocating storage for `cloneFactory` if it is a non-storage
129     // type.
130     std::tuple<CloneFactory, UniquePtr<T>> data;
131 
132     inline const CloneFactory& cloneFactory() const {
133         return std::get<0>(data);
134     }
135 
136     inline const UniquePtr<T>& ptr() const {
137         return std::get<1>(data);
138     }
139 
140     inline UniquePtr<T>& ptr() {
141         return std::get<1>(data);
142     }
143 
144     inline const auto& _makeEqualityLens() const noexcept {
145         return this->ptr();
146     }
147 
148     inline const auto& _makeStrictWeakOrderLens() const noexcept {
149         return this->ptr();
150     }
151 
152     static inline UniquePtr<T> clone_with_factory_impl(const T& copy, const CloneFactory& factory) {
153         return UniquePtr<T>{factory(copy)};
154     }
155 
156     template <typename Pointerlike>
157     static inline UniquePtr<T> clone_with_factory(Pointerlike&& copy, const CloneFactory& factory) {
158         if (!copy)
159             return nullptr;
160         return clone_with_factory_impl(*copy, factory);
161     }
162 
163     struct internal_construction {};
164 
165     explicit inline clonable_ptr(UniquePtr<T>&& p,
166                                  const CloneFactory* const f,
167                                  const internal_construction&)
168         : data(*f, std::move(p)) {}
169 
170     explicit inline clonable_ptr(UniquePtr<T>&& p, CloneFactory&& f, const internal_construction&)
171         : data(std::move(f), std::move(p)) {}
172 
173 public:
174     /*! Destroys this pointer.  Functions like `std::unique_ptr`. */
175     inline ~clonable_ptr() noexcept = default;
176 
177     /*! Moves a value, by pointer.  Functions like `std::unique_ptr`. */
178     inline clonable_ptr(clonable_ptr&&) noexcept(
179         noexcept(CloneFactory{std::declval<CloneFactory>()}) &&
180         noexcept(UniquePtr<T>{std::declval<UniquePtr<T>>()})) = default;
181 
182     /*! Moves a value, by pointer.  Functions like `std::unique_ptr`. */
183     inline clonable_ptr& operator=(clonable_ptr&&) &
184         noexcept(noexcept(std::declval<CloneFactory>() = std::declval<CloneFactory>()) &&
185                  noexcept(std::declval<UniquePtr<T>>() = std::declval<UniquePtr<T>>())) = default;
186 
187     /*!
188      * Constructs a pointer referring to a new copy of an original value.  The old object owned by
189      * `*this` will be deleted, and `*this` will manage a new copy of `copy`, as created by
190      * `copy->clone()`.  If `copy` is not managing anything (its internal pointer is `nullptr`),
191      * then this new copy will also be nullptr.
192      *
193      * POST: `copy != nullptr ? copy != *this : copy == *this` -- If `copy` stores a pointer to a
194      * value, then `*this` will have an independent pointer.  If `copy` stores `nullptr`, then
195      * `*this` will also store `nullptr`.
196      *
197      * `copy`: The original value to copy.
198      * THROWS: Any exceptions thrown by `cloneFactory( *copy )`.
199      * TODO: Consider adding a noexcept deduction specifier to this copy operation.
200      */
201     inline clonable_ptr(const clonable_ptr& copy)
202         : data{copy.cloneFactory(), clone_with_factory(copy, copy.cloneFactory())} {}
203 
204     /*!
205      * Constructs a pointer referring to a new copy of an original value.  The old object owned by
206      * `*this` will be deleted, and `*this` will manage a new copy of `copy`, as created by
207      * `copy->clone()`.  If `copy` is not managing anything (its internal pointer is `nullptr`),
208      * then this new copy will also be nullptr.
209      *
210      * POST: `copy != nullptr ? copy != *this : copy == *this` -- If `copy` stores a pointer to a
211      * value, then `*this` will have an independent pointer.  If `copy` stores `nullptr`, then
212      * `*this` will also store `nullptr`.
213      *
214      * NOTE: The `CloneFactory` will be copied from the `copy` poiner, by default.
215      *
216      * `copy`: The original value to copy.
217      * `factory`: The factory to use for cloning.  Defaults to the source's factory.
218      * THROWS: Any exceptions thrown by `factory( *copy )`.
219      * TODO: Consider adding a noexcept deduction specifier to this copy operation.
220      */
221     inline clonable_ptr(const clonable_ptr& copy, const CloneFactory& factory)
222         : data{factory, clone_with_factory(copy, factory)} {}
223 
224     /*!
225      * Changes the value of this pointer, by creating a new object having the same value as `copy`.
226      * The old object owned by `*this` will be deleted, and `*this` will manage a new copy of
227      * `copy`, as created by `copy->clone()`.  If `copy` is not managing anything (its internal
228      * pointer is `nullptr`), then this new copy will also be nullptr.
229      *
230      * NOTE: This operation cannot be conducted on an xvalue or prvalue instance.  (This prevents
231      * silliness such as: `func_returning_ptr()= some_other_func_returning_ptr();`)
232      *
233      * NOTE: `copy`'s `CloneFactory` will be used to copy.
234      *
235      * POST: `copy != nullptr ? copy != *this : copy == *this` -- If `copy` stores a pointer to a
236      * value, then `*this` will have an independent pointer.  If `copy` stores `nullptr`, then
237      * `*this` will also store `nullptr`.
238      *
239      * `copy`: The value to make a copy of.
240      * RETURNS: A reference to this pointer, after modification.
241      * TODO: Consider adding a noexcept deduction specifier to this copy operation.
242      */
243     inline clonable_ptr& operator=(const clonable_ptr& copy) & {
244         return *this = clonable_ptr{copy};
245     }
246 
247     // Maintenance note: The two enable_if overloads of `clonable_ptr( std::nullptr_t )` are
248     // necessary, due to the fact that `std::nullptr_t` is capable of implicit conversion to a
249     // built-in pointer type.  If the stateful form being deleted causes the `nullptr` to convert,
250     // this could cause binding to another ctor which may be undesired.
251 
252     /*!
253      * `nullptr` construct a clonable pointer (to `nullptr`), if the `CloneFactory` type is
254      * stateless.
255      * The value will be a pointer to nothing, with a default `CloneFactory`.
256      * NOTE: This constructor is only available for types with a stateless `CloneFactory` type.
257      */
258     template <typename CloneFactory_ = CloneFactory>
259     inline clonable_ptr(
260         typename std::enable_if<std::is_empty<CloneFactory_>::value, std::nullptr_t>::type) {}
261 
262     /*!
263      * Disable `nullptr` construction of clonable pointer (to `nullptr`), if the `CloneFactory` type
264      * is stateful.
265      * NOTE: This constructor is disabled for types with a stateless `CloneFactory` type.
266      */
267     template <typename CloneFactory_ = CloneFactory>
268     inline clonable_ptr(typename std::enable_if<!std::is_empty<CloneFactory_>::value,
269                                                 std::nullptr_t>::type) = delete;
270 
271     /*!
272      * Constructs a pointer to nothing, with a default `CloneFactory`.
273      * This function is unavailable when `CloneFactory` is stateful.
274      */
275     template <typename CloneFactory_ = CloneFactory,
276               typename = typename std::enable_if<std::is_empty<CloneFactory_>::value>::type>
277     explicit inline clonable_ptr() noexcept {}
278 
279     /*! Constructs a pointer to nothing, with the specified `CloneFactory`. */
280     explicit inline clonable_ptr(CloneFactory factory) : data{factory, nullptr} {}
281 
282     /*!
283      * Constructs a `clonable_ptr` which owns `p`, initializing the stored pointer with `p`.
284      * This function is unavailable when `CloneFactory` is stateful.
285      * `p`: The pointer to take ownership of.
286      */
287     template <typename CloneFactory_ = CloneFactory>
288     explicit inline clonable_ptr(
289         typename std::enable_if<std::is_empty<CloneFactory_>::value, T* const>::type p)
290         : clonable_ptr(UniquePtr<T>{p}) {}
291 
292     /*!
293      * Disable single-argument construction of clonable pointer (with a raw pointer), if the
294      * `CloneFactory` type is stateful.
295      * NOTE: This constructor is disabled for types with a stateless `CloneFactory` type.
296      */
297     template <typename CloneFactory_ = CloneFactory>
298     explicit inline clonable_ptr(
299         typename std::enable_if<!std::is_empty<CloneFactory_>::value, T* const>::type) = delete;
300 
301     // The reason that we have two overloads for clone factory is to ensure that we avoid as many
302     // exception-unsafe uses as possible.  The const-lvalue-reference variant in conjunction with
303     // the rvalue-reference variant lets us separate the cases of "constructed in place" from
304     // "passed from a local".  In the latter case, we can't make our type any safer, since the
305     // timing of the construction of the local and the timing of the `new` on the raw pointer are
306     // out of our control.  At least we prevent an accidental use which SEEMS exception safe but
307     // isn't -- hopefully highlighting exception unsafe code, by making it more explicit.  In the
308     // former, "constructed in place", case, we are able to successfully move construct without
309     // exception problems, if it's nothrow move constructible.  If it isn't we flag a compiler
310     // error.  In this case, too, we prevent accidental use which SEEMS exception safe and hopefully
311     // will similarly highlight exception unsafe code.
312 
313     /*!
314      * Constructs a `clonable_ptr` which owns `p`, initializing the stored pointer with `p`.  The
315      * `factory` parameter will be used as the `CloneFactory`
316      * `p`: The pointer to take ownership of.
317      * `factory`: The clone factory to use in future copies.
318      * NOTE: It is not recommended to use this constructor, as the following is not exception safe
319      * code:
320      * ~~~
321      * std::function<T* ()> cloner= [](const T& p){ return p; };
322      * auto getCloner= [=]{ return cloner; };
323      * clonable_ptr<T, std::function<T* ()>> bad{new T, getCloner()}; // BAD IDEA!!!
324      * ~~~
325      * Even if the above could be made exception safe, there are other more complicated use cases
326      * which would not be exception safe.  (The above is not exception safe, because the `new T`
327      * expression can be evaluated before the `getCloner()` expression is evaluated.  `getCloner()`
328      * is allowed to throw, thus leaving `new T` to be abandoned.
329      */
330     explicit inline clonable_ptr(T* const p, const CloneFactory& factory)
331         : clonable_ptr{UniquePtr<T>{p}, std::addressof(factory), internal_construction{}} {}
332 
333     /*!
334      * We forbid construction of a `clonable_ptr` from an unmanaged pointer, when specifying
335      * a cloning function -- regardless of whether the `CloneFactory` is stateful or not.
336      * NOTE: We have disabled this constructor, as the following is not exception safe
337      * code:
338      * ~~~
339      * clonable_ptr<T, std::function<T* ()>> bad{new T, [](const T& p){ return p; }}; // BAD IDEA!!!
340      * ~~~
341      * Even if the above could be made exception safe, there are other more complicated use cases
342      * which would not be exception safe.  (The above is not exception safe, because the `new T`
343      * expression can be evaluated before the lambda expression is evaluated and converted to a
344      * `std::function`.  The `std::function` constructor is allowed to throw, thus leaving `new T`
345      * to be abandoned.  More complicated cases are completely hidden from `clonable_ptr`'s
346      * inspection, thus making this constructor too dangerous to exist.
347      */
348     explicit inline clonable_ptr(T* const p, CloneFactory&& factory) = delete;
349 
350     /*!
351      * Constructs a `nullptr` valued clonable pointer, with a specified `CloneFactory`, `factory`.
352      */
353     explicit inline clonable_ptr(std::nullptr_t, CloneFactory&& factory)
354         : clonable_ptr{UniquePtr<T>{nullptr}, std::move(factory), internal_construction{}} {}
355 
356     /*!
357      * Constructs a `clonable_ptr` by transferring ownership from `p` to `*this`.  A default
358      * `CloneFactory` will be provided for future copies.
359      * `p`: The pointer to take ownership of.
360      * NOTE: This constructor allows for implicit conversion from a `UniquePtr` (xvalue) object.
361      * NOTE: This constructor is unavailable when `CloneFactory` is stateful.
362      * NOTE: This usage should be preferred over the raw-pointer construction forms, when using
363      * factories as constructor arguments, as in the following exception safe code:
364      * ~~~
365      * clonable_ptr<T, std::function<T* ()>> good{std::make_unique<T>(),
366      *                                            [](const T& p){ return p; }}; // GOOD IDEA!!!
367      * ~~~
368      */
369     template <typename CloneFactory_ = CloneFactory,
370               typename Derived,
371               typename = typename std::enable_if<std::is_empty<CloneFactory_>::value>::type>
372     inline clonable_ptr(UniquePtr<Derived> p) : data{CloneFactory{}, std::move(p)} {}
373 
374     /*!
375      * Constructs a `clonable_ptr` by transferring ownership from `p` to `*this`.  The `factory`
376      * parameter will be used as the `CloneFactory` for future copies.
377      * NOTE: This constructor allows for implicit conversion from a `UniquePtr` (xvalue) object.
378      * `p`: The pointer to take ownership of.
379      * `factory`: The clone factory to use in future copies.
380      * NOTE: This usage should be preferred over the raw-pointer construction forms, when using
381      * factories as constructor arguments, as in the following exception safe code:
382      * ~~~
383      * clonable_ptr<T, std::function<T* ()>> good{std::make_unique<T>(),
384      *                                            [](const T& p){ return p; }}; // GOOD IDEA!!!
385      * ~~~
386      */
387     template <typename Derived>
388     inline clonable_ptr(UniquePtr<Derived> p, CloneFactory factory)
389         : data{std::move(factory), std::move(p)} {}
390 
391     /*!
392      * Changes the value of this pointer, by creating a new object having the same value as `copy`.
393      * The old object owned by `*this` will be deleted, and `*this` will manage a new copy of
394      * `copy`, as created by `copy->clone()`.  If `copy` is not managing anything (its internal
395      * pointer is `nullptr`), then this new copy will also be nullptr.
396      *
397      * NOTE: This operation cannot be performed on an xvalue or prvalue instance.  (This prevents
398      * silliness such as: `func_returning_ptr()= some_other_func_returning_ptr();`)
399      *
400      * NOTE: `copy`'s `CloneFactory` will be used to copy.
401      *
402      * POST: `copy != nullptr ? copy != *this : copy == *this` -- If `copy` stores a pointer to a
403      * value, then `*this` will have an independent pointer.  If `copy` stores `nullptr`, then
404      * `*this` will also store `nullptr`.
405      *
406      * `copy`: The value to make a copy of.
407      * RETURNS: A reference to this pointer, after modification.
408      */
409     inline clonable_ptr& operator=(UniquePtr<T> copy) & {
410         return *this = std::move(clonable_ptr{std::move(copy), this->cloneFactory()});
411     }
412 
413     template <typename Derived>
414     inline clonable_ptr& operator=(UniquePtr<Derived> copy) & {
415         return *this = std::move(clonable_ptr{std::move(copy), this->cloneFactory()});
416     }
417 
418     /*!
419      * Change the `CloneFactory` for `*this` to `factory`.
420      * NOTE: This operation cannot be performed on an xvalue or prvalue instance.  (This prevents
421      * silliness such as: `func_returning_ptr().setCloneFactory( factory );`.)
422      */
423     template <typename FactoryType>
424     inline void setCloneFactory(FactoryType&& factory) & {
425         this->cloneFactory() = std::forward<FactoryType>(factory);
426     }
427 
428     /*!
429      * Dereferences the pointer owned by `*this`.
430      * NOTE: The behavior is undefined if `this->get() == nullptr`.
431      * RETURNS: The object owned by `*this`, equivalent to `*get()`.
432      */
433     inline auto& operator*() const {
434         return *this->ptr();
435     }
436 
437     /*!
438      * Dereferences the pointer owned by `*this`.
439      * NOTE: The behavior is undefined if `this->get() == nullptr`.
440      * RETURNS: A pointer to the object owned by `*this`, equivalent to `get()`.
441      */
442     inline auto* operator-> () const {
443         return this->ptr().operator->();
444     }
445 
446     /*!
447      * Returns `true` if `*this` owns a pointer to a value, and `false` otherwise.
448      * RETURNS: A value equivalent to `static_cast< bool >( this->get() )`.
449      */
450     explicit inline operator bool() const noexcept {
451         return this->ptr().get();
452     }
453 
454     /*!
455      * Converts `*this` to a `UniquePtr< T >` by transferring ownership.  This function will retire
456      * ownership of the pointer owned by `*this`.  This is a safe operation, as this function cannot
457      * be called from an lvalue context -- rvalue operations are used to represent transfer of
458      * ownership semantics.
459      *
460      * NOTE: This function is only applicable in `rvalue` contexts.
461      * NOTE: This function has transfer of ownership semantics.
462      *
463      * RETURNS: A `UniquePtr< T >` which owns the pointer formerly managed by `*this`.
464      */
465     inline operator UniquePtr<T>() && {
466         return std::move(this->ptr());
467     }
468 
469     /*! Provides a constant `UniquePtr< T >` view of the object owned by `*this`. */
470     inline operator const UniquePtr<T>&() const& {
471         return this->ptr();
472     }
473 
474     /*! Provides a mutable `UniquePtr< T >` view of the object owned by `*this`. */
475     inline operator UniquePtr<T>&() & {
476         return this->ptr();
477     }
478 
479     /*! Provides a C-style `T *` pointer to the object owned by `*this`. */
480     inline T* get() const {
481         return this->ptr().get();
482     }
483 
484     inline void reset() & noexcept {
485         this->ptr().reset();
486     }
487 
488     inline void reset(T* const p) & {
489         this->ptr().reset(p);
490     }
491 
492     // Equality
493 
494     inline friend bool operator==(const clonable_ptr& lhs, const clonable_ptr& rhs) {
495         return lhs._makeEqualityLens() == rhs._makeEqualityLens();
496     }
497 
498     template <template <typename, typename...> class U, typename... UArgs>
499     inline friend bool operator==(const U<T, UArgs...>& lhs, const clonable_ptr& rhs) {
500         return lhs == rhs._makeEqualityLens();
501     }
502 
503     template <template <typename, typename...> class U, typename... UArgs>
504     inline friend bool operator==(const clonable_ptr& lhs, const U<T, UArgs...>& rhs) {
505         return lhs._makeEqualityLens() == rhs;
506     }
507 
508     inline friend bool operator==(const std::nullptr_t& lhs, const clonable_ptr& rhs) {
509         return lhs == rhs._makeEqualityLens();
510     }
511 
512     inline friend bool operator==(const clonable_ptr& lhs, const std::nullptr_t& rhs) {
513         return lhs._makeEqualityLens() == rhs;
514     }
515 
516     // Strict weak order
517 
518     inline friend bool operator<(const clonable_ptr& lhs, const clonable_ptr& rhs) {
519         return lhs._makeStrictWeakOrderLens() < rhs._makeStrictWeakOrderLens();
520     }
521 
522     template <template <typename, typename...> class U, typename... UArgs>
523     inline friend bool operator<(const U<T, UArgs...>& lhs, const clonable_ptr& rhs) {
524         return lhs < rhs._makeStrictWeakOrderLens();
525     }
526 
527     template <template <typename, typename...> class U, typename... UArgs>
528     inline friend bool operator<(const clonable_ptr& lhs, const U<T, UArgs...>& rhs) {
529         return lhs._makeStrictWeakOrderLens() < rhs;
530     }
531 
532     inline friend bool operator<(const std::nullptr_t& lhs, const clonable_ptr& rhs) {
533         return lhs < rhs._makeStrictWeakOrderLens();
534     }
535 
536     inline friend bool operator<(const clonable_ptr& lhs, const std::nullptr_t& rhs) {
537         return lhs._makeStrictWeakOrderLens() < rhs;
538     }
539 };
540 
541 // Inequality
542 
543 template <typename C, typename F, template <typename, typename...> class U>
544 inline bool operator!=(const clonable_ptr<C, F, U>& lhs, const clonable_ptr<C, F, U>& rhs) {
545     return !(lhs == rhs);
546 }
547 
548 template <typename C, typename F, template <typename, typename...> class U, typename... UArgs>
549 inline bool operator!=(const U<C, UArgs...>& lhs, const clonable_ptr<C, F, U>& rhs) {
550     return !(lhs == rhs);
551 }
552 
553 template <typename C, typename F, template <typename, typename...> class U, typename... UArgs>
554 inline bool operator!=(const clonable_ptr<C, F, U>& lhs, const U<C, UArgs...>& rhs) {
555     return !(lhs == rhs);
556 }
557 
558 template <typename C, typename F, template <typename, typename...> class U>
559 inline bool operator!=(const std::nullptr_t& lhs, const clonable_ptr<C, F, U>& rhs) {
560     return !(lhs == rhs);
561 }
562 
563 template <typename C, typename F, template <typename, typename...> class U>
564 inline bool operator!=(const clonable_ptr<C, F, U>& lhs, const std::nullptr_t& rhs) {
565     return !(lhs == rhs);
566 }
567 
568 // Greater than
569 
570 template <typename C, typename F, template <typename, typename...> class U>
571 inline bool operator>(const clonable_ptr<C, F, U>& lhs, const clonable_ptr<C, F, U>& rhs) {
572     return rhs < lhs;
573 }
574 
575 template <typename C, typename F, template <typename, typename...> class U, typename... UArgs>
576 inline bool operator>(const U<C, UArgs...>& lhs, const clonable_ptr<C, F, U>& rhs) {
577     return rhs < lhs;
578 }
579 
580 template <typename C, typename F, template <typename, typename...> class U, typename... UArgs>
581 inline bool operator>(const clonable_ptr<C, F, U>& lhs, const U<C, UArgs...>& rhs) {
582     return rhs < lhs;
583 }
584 
585 template <typename C, typename F, template <typename, typename...> class U>
586 inline bool operator>(const std::nullptr_t& lhs, const clonable_ptr<C, F, U>& rhs) {
587     return rhs < lhs;
588 }
589 
590 template <typename C, typename F, template <typename, typename...> class U>
591 inline bool operator>(const clonable_ptr<C, F, U>& lhs, const std::nullptr_t& rhs) {
592     return rhs < lhs;
593 }
594 
595 // Equal or Less
596 
597 template <typename C, typename F, template <typename, typename...> class U>
598 inline bool operator<=(const clonable_ptr<C, F, U>& lhs, const clonable_ptr<C, F, U>& rhs) {
599     return !(lhs > rhs);
600 }
601 
602 template <typename C, typename F, template <typename, typename...> class U, typename... UArgs>
603 inline bool operator<=(const U<C, UArgs...>& lhs, const clonable_ptr<C, F, U>& rhs) {
604     return !(lhs > rhs);
605 }
606 
607 template <typename C, typename F, template <typename, typename...> class U, typename... UArgs>
608 inline bool operator<=(const clonable_ptr<C, F, U>& lhs, const U<C, UArgs...>& rhs) {
609     return !(lhs > rhs);
610 }
611 
612 template <typename C, typename F, template <typename, typename...> class U>
613 inline bool operator<=(const std::nullptr_t& lhs, const clonable_ptr<C, F, U>& rhs) {
614     return !(lhs > rhs);
615 }
616 
617 template <typename C, typename F, template <typename, typename...> class U>
618 inline bool operator<=(const clonable_ptr<C, F, U>& lhs, const std::nullptr_t& rhs) {
619     return !(lhs > rhs);
620 }
621 
622 // Equal or greater
623 
624 template <typename C, typename F, template <typename, typename...> class U>
625 inline bool operator>=(const clonable_ptr<C, F, U>& lhs, const clonable_ptr<C, F, U>& rhs) {
626     return !(lhs < rhs);
627 }
628 
629 template <typename C, typename F, template <typename, typename...> class U, typename... UArgs>
630 inline bool operator>=(const U<C, UArgs...>& lhs, const clonable_ptr<C, F, U>& rhs) {
631     return !(lhs < rhs);
632 }
633 
634 template <typename C, typename F, template <typename, typename...> class U, typename... UArgs>
635 inline bool operator>=(const clonable_ptr<C, F, U>& lhs, const U<C, UArgs...>& rhs) {
636     return !(lhs < rhs);
637 }
638 
639 template <typename C, typename F, template <typename, typename...> class U>
640 inline bool operator>=(const std::nullptr_t& lhs, const clonable_ptr<C, F, U>& rhs) {
641     return !(lhs < rhs);
642 }
643 
644 template <typename C, typename F, template <typename, typename...> class U>
645 inline bool operator>=(const clonable_ptr<C, F, U>& lhs, const std::nullptr_t& rhs) {
646     return !(lhs < rhs);
647 }
648 }  // namespace mongo
649