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