summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/base/SConscript9
-rw-r--r--src/mongo/base/clonable_ptr.h656
-rw-r--r--src/mongo/base/clonable_ptr_test.cpp954
-rw-r--r--src/mongo/base/concept/README5
-rw-r--r--src/mongo/base/concept/assignable.h13
-rw-r--r--src/mongo/base/concept/clonable.h20
-rw-r--r--src/mongo/base/concept/clone_factory.h21
-rw-r--r--src/mongo/base/concept/constructible.h38
-rw-r--r--src/mongo/base/concept/convertible_to.h14
-rw-r--r--src/mongo/base/concept/copy_assignable.h18
-rw-r--r--src/mongo/base/concept/copy_constructible.h14
-rw-r--r--src/mongo/base/concept/unique_ptr.h41
12 files changed, 0 insertions, 1803 deletions
diff --git a/src/mongo/base/SConscript b/src/mongo/base/SConscript
index af40fdab72a..848aca3b7f0 100644
--- a/src/mongo/base/SConscript
+++ b/src/mongo/base/SConscript
@@ -55,15 +55,6 @@ env.CppUnitTest(
],
)
-env.CppUnitTest(
- target=[
- 'clonable_ptr_test',
- ],
- source=[
- 'clonable_ptr_test.cpp',
- ],
-)
-
env.Library(
target=[
'secure_allocator'
diff --git a/src/mongo/base/clonable_ptr.h b/src/mongo/base/clonable_ptr.h
deleted file mode 100644
index fc5c6bb39a4..00000000000
--- a/src/mongo/base/clonable_ptr.h
+++ /dev/null
@@ -1,656 +0,0 @@
-// clonable_ptr.h
-
-/*-
- * Copyright (C) 2016 MongoDB Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects
- * for all of the code used other than as permitted herein. If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so. If you do not
- * wish to do so, delete this exception statement from your version. If you
- * delete this exception statement from all source files in the program,
- * then also delete it in the license file.
- */
-
-#pragma once
-
-#include <cstddef>
-#include <memory>
-#include <tuple>
-#include <type_traits>
-
-namespace mongo {
-namespace clonable_ptr_detail {
-// This is the default `CloneFactory` conforming to `mongo::concept::CloneFactory` for
-// `clonable_ptr`.
-template <typename Clonable>
-struct CloneFactory {
- auto operator()(const Clonable& c) const -> decltype(c.clone()) {
- return c.clone();
- }
-};
-
-// TODO: Move some of these traits detection structs to a template metaprogramming header.
-template <typename T>
-struct detect_clone_factory_type_member_impl {
- struct Fallback {
- struct clone_factory_type {};
- };
-
- struct Derived : T, Fallback {};
-
- using Yes = char[2];
- using No = char[1];
-
- template <typename U>
- static No& test(typename U::clone_factory_type*);
-
- template <typename U>
- static Yes& test(U*);
-
- static constexpr bool value = sizeof(test<Derived>(0)) == sizeof(Yes);
-
- using type = typename std::integral_constant<bool, value>::type;
-};
-
-template <typename T>
-struct detect_clone_factory_type_member : std::conditional<std::is_class<T>::value,
- detect_clone_factory_type_member_impl<T>,
- std::false_type>::type {};
-
-template <typename T, bool has_clone_factory_member = detect_clone_factory_type_member<T>::value>
-struct clonable_traits_impl;
-
-template <typename T>
-struct clonable_traits_impl<T, false> {
- using clone_factory_type = CloneFactory<T>;
-};
-
-template <typename T>
-struct clonable_traits_impl<T, true> {
- using clone_factory_type = typename T::clone_factory_type;
-};
-} // namespace clonable_ptr_detail
-
-/**
- * The 'clonable_traits' class is a specializable traits class for clonable-like types. By
- * specializing this traits class for a type it is possible to change the global default
- * `CloneFactory` type for a specific type. Types which conform to `mongo::concept::Clonable`
- * will get a default `CloneFactory` type whch invokes their specific `Clonable::clone` function. A
- * specialization can be used to make a type use a different clone factory function. A type `T` may
- * specify `T::clone_factory_type` instead of specializing this traits type.
- */
-template <typename T>
-struct clonable_traits : clonable_ptr_detail::clonable_traits_impl<T> {};
-
-/**
- * The `clonable_ptr` represents a value-like type held at a distance. The `clonable_ptr` class is
- * a smart-pointer type which functions like a `std::unique_ptr` with the added ability to create
- * new copies of the pointee on copy construction. The default CloneFactory assumes that `T` is a
- * type which models the Concept `mongo::concept::Clonable`. The supplied type may supply an
- * alternative default `CloneFactory` type by either of two means:
- *
- * * `T` may define a member `T::clone_factory_type` which conforms to
- * `mongo::concept::CloneFactory`
- * * `T` may have an accompanying specialization of `mongo::clonable_traits< T >` which
- * defines `clonable_factory_type`.
- *
- * NOTE: The `CloneFactory` type is permitted to be stateful, but must be copy constructible and
- * copy assignable.
- * NOTE: The `CloneFactory` member does NOT participate in value comparisons for a `clonable_ptr`,
- * even when it has state.
- *
- * `T`: The type of the object being managed.
- * `CloneFactory`: A type which models the Concept `mongo::concept::CloneFactory`.
- * `UniquePtr`: A type which models the Concept `mongo::concept::UniquePtr`
- */
-template <typename T,
- typename CloneFactory = typename clonable_traits<T>::clone_factory_type,
- template <typename, typename...> class UniquePtr = std::unique_ptr>
-class clonable_ptr {
-private:
- // `std::tuple` is used to avoid allocating storage for `cloneFactory` if it is a non-storage
- // type.
- std::tuple<CloneFactory, UniquePtr<T>> data;
-
- inline const CloneFactory& cloneFactory() const {
- return std::get<0>(data);
- }
-
- inline const UniquePtr<T>& ptr() const {
- return std::get<1>(data);
- }
-
- inline UniquePtr<T>& ptr() {
- return std::get<1>(data);
- }
-
- inline const auto& _makeEqualityLens() const noexcept {
- return this->ptr();
- }
-
- inline const auto& _makeStrictWeakOrderLens() const noexcept {
- return this->ptr();
- }
-
- static inline UniquePtr<T> clone_with_factory_impl(const T& copy, const CloneFactory& factory) {
- return UniquePtr<T>{factory(copy)};
- }
-
- template <typename Pointerlike>
- static inline UniquePtr<T> clone_with_factory(Pointerlike&& copy, const CloneFactory& factory) {
- if (!copy)
- return nullptr;
- return clone_with_factory_impl(*copy, factory);
- }
-
- struct internal_construction {};
-
- explicit inline clonable_ptr(UniquePtr<T>&& p,
- const CloneFactory* const f,
- const internal_construction&)
- : data(*f, std::move(p)) {}
-
- explicit inline clonable_ptr(UniquePtr<T>&& p, CloneFactory&& f, const internal_construction&)
- : data(std::move(f), std::move(p)) {}
-
-public:
- /*! Destroys this pointer. Functions like `std::unique_ptr`. */
- inline ~clonable_ptr() noexcept = default;
-
- /*! Moves a value, by pointer. Functions like `std::unique_ptr`. */
- inline clonable_ptr(clonable_ptr&&) noexcept(
- noexcept(CloneFactory{std::declval<CloneFactory>()}) &&
- noexcept(UniquePtr<T>{std::declval<UniquePtr<T>>()})) = default;
-
- /*! Moves a value, by pointer. Functions like `std::unique_ptr`. */
- inline clonable_ptr& operator=(clonable_ptr&&) &
- noexcept(noexcept(std::declval<CloneFactory>() = std::declval<CloneFactory>()) &&
- noexcept(std::declval<UniquePtr<T>>() = std::declval<UniquePtr<T>>())) = default;
-
- /*!
- * Constructs a pointer referring to a new copy of an original value. The old object owned by
- * `*this` will be deleted, and `*this` will manage a new copy of `copy`, as created by
- * `copy->clone()`. If `copy` is not managing anything (its internal pointer is `nullptr`),
- * then this new copy will also be nullptr.
- *
- * POST: `copy != nullptr ? copy != *this : copy == *this` -- If `copy` stores a pointer to a
- * value, then `*this` will have an independent pointer. If `copy` stores `nullptr`, then
- * `*this` will also store `nullptr`.
- *
- * `copy`: The original value to copy.
- * THROWS: Any exceptions thrown by `cloneFactory( *copy )`.
- * TODO: Consider adding a noexcept deduction specifier to this copy operation.
- */
- inline clonable_ptr(const clonable_ptr& copy)
- : data{copy.cloneFactory(), clone_with_factory(copy, copy.cloneFactory())} {}
-
- /*!
- * Constructs a pointer referring to a new copy of an original value. The old object owned by
- * `*this` will be deleted, and `*this` will manage a new copy of `copy`, as created by
- * `copy->clone()`. If `copy` is not managing anything (its internal pointer is `nullptr`),
- * then this new copy will also be nullptr.
- *
- * POST: `copy != nullptr ? copy != *this : copy == *this` -- If `copy` stores a pointer to a
- * value, then `*this` will have an independent pointer. If `copy` stores `nullptr`, then
- * `*this` will also store `nullptr`.
- *
- * NOTE: The `CloneFactory` will be copied from the `copy` poiner, by default.
- *
- * `copy`: The original value to copy.
- * `factory`: The factory to use for cloning. Defaults to the source's factory.
- * THROWS: Any exceptions thrown by `factory( *copy )`.
- * TODO: Consider adding a noexcept deduction specifier to this copy operation.
- */
- inline clonable_ptr(const clonable_ptr& copy, const CloneFactory& factory)
- : data{factory, clone_with_factory(copy, factory)} {}
-
- /*!
- * Changes the value of this pointer, by creating a new object having the same value as `copy`.
- * The old object owned by `*this` will be deleted, and `*this` will manage a new copy of
- * `copy`, as created by `copy->clone()`. If `copy` is not managing anything (its internal
- * pointer is `nullptr`), then this new copy will also be nullptr.
- *
- * NOTE: This operation cannot be conducted on an xvalue or prvalue instance. (This prevents
- * silliness such as: `func_returning_ptr()= some_other_func_returning_ptr();`)
- *
- * NOTE: `copy`'s `CloneFactory` will be used to copy.
- *
- * POST: `copy != nullptr ? copy != *this : copy == *this` -- If `copy` stores a pointer to a
- * value, then `*this` will have an independent pointer. If `copy` stores `nullptr`, then
- * `*this` will also store `nullptr`.
- *
- * `copy`: The value to make a copy of.
- * RETURNS: A reference to this pointer, after modification.
- * TODO: Consider adding a noexcept deduction specifier to this copy operation.
- */
- inline clonable_ptr& operator=(const clonable_ptr& copy) & {
- return *this = clonable_ptr{copy};
- }
-
- // Maintenance note: The two enable_if overloads of `clonable_ptr( std::nullptr_t )` are
- // necessary, due to the fact that `std::nullptr_t` is capable of implicit conversion to a
- // built-in pointer type. If the stateful form being deleted causes the `nullptr` to convert,
- // this could cause binding to another ctor which may be undesired.
-
- /*!
- * `nullptr` construct a clonable pointer (to `nullptr`), if the `CloneFactory` type is
- * stateless.
- * The value will be a pointer to nothing, with a default `CloneFactory`.
- * NOTE: This constructor is only available for types with a stateless `CloneFactory` type.
- */
- template <typename CloneFactory_ = CloneFactory>
- inline clonable_ptr(
- typename std::enable_if<std::is_empty<CloneFactory_>::value, std::nullptr_t>::type) {}
-
- /*!
- * Disable `nullptr` construction of clonable pointer (to `nullptr`), if the `CloneFactory` type
- * is stateful.
- * NOTE: This constructor is disabled for types with a stateless `CloneFactory` type.
- */
- template <typename CloneFactory_ = CloneFactory>
- inline clonable_ptr(typename std::enable_if<!std::is_empty<CloneFactory_>::value,
- std::nullptr_t>::type) = delete;
-
- /*!
- * Constructs a pointer to nothing, with a default `CloneFactory`.
- * This function is unavailable when `CloneFactory` is stateful.
- */
- template <typename CloneFactory_ = CloneFactory,
- typename = typename std::enable_if<std::is_empty<CloneFactory_>::value>::type>
- explicit inline clonable_ptr() noexcept {}
-
- /*! Constructs a pointer to nothing, with the specified `CloneFactory`. */
- explicit inline clonable_ptr(CloneFactory factory) : data{factory, nullptr} {}
-
- /*!
- * Constructs a `clonable_ptr` which owns `p`, initializing the stored pointer with `p`.
- * This function is unavailable when `CloneFactory` is stateful.
- * `p`: The pointer to take ownership of.
- */
- template <typename CloneFactory_ = CloneFactory>
- explicit inline clonable_ptr(
- typename std::enable_if<std::is_empty<CloneFactory_>::value, T* const>::type p)
- : clonable_ptr(UniquePtr<T>{p}) {}
-
- /*!
- * Disable single-argument construction of clonable pointer (with a raw pointer), if the
- * `CloneFactory` type is stateful.
- * NOTE: This constructor is disabled for types with a stateless `CloneFactory` type.
- */
- template <typename CloneFactory_ = CloneFactory>
- explicit inline clonable_ptr(
- typename std::enable_if<!std::is_empty<CloneFactory_>::value, T* const>::type) = delete;
-
- // The reason that we have two overloads for clone factory is to ensure that we avoid as many
- // exception-unsafe uses as possible. The const-lvalue-reference variant in conjunction with
- // the rvalue-reference variant lets us separate the cases of "constructed in place" from
- // "passed from a local". In the latter case, we can't make our type any safer, since the
- // timing of the construction of the local and the timing of the `new` on the raw pointer are
- // out of our control. At least we prevent an accidental use which SEEMS exception safe but
- // isn't -- hopefully highlighting exception unsafe code, by making it more explicit. In the
- // former, "constructed in place", case, we are able to successfully move construct without
- // exception problems, if it's nothrow move constructible. If it isn't we flag a compiler
- // error. In this case, too, we prevent accidental use which SEEMS exception safe and hopefully
- // will similarly highlight exception unsafe code.
-
- /*!
- * Constructs a `clonable_ptr` which owns `p`, initializing the stored pointer with `p`. The
- * `factory` parameter will be used as the `CloneFactory`
- * `p`: The pointer to take ownership of.
- * `factory`: The clone factory to use in future copies.
- * NOTE: It is not recommended to use this constructor, as the following is not exception safe
- * code:
- * ~~~
- * std::function<T* ()> cloner= [](const T& p){ return p; };
- * auto getCloner= [=]{ return cloner; };
- * clonable_ptr<T, std::function<T* ()>> bad{new T, getCloner()}; // BAD IDEA!!!
- * ~~~
- * Even if the above could be made exception safe, there are other more complicated use cases
- * which would not be exception safe. (The above is not exception safe, because the `new T`
- * expression can be evaluated before the `getCloner()` expression is evaluated. `getCloner()`
- * is allowed to throw, thus leaving `new T` to be abandoned.
- */
- explicit inline clonable_ptr(T* const p, const CloneFactory& factory)
- : clonable_ptr{UniquePtr<T>{p}, std::addressof(factory), internal_construction{}} {}
-
- /*!
- * Constructs a `clonable_ptr` which owns `p`, initializing the stored pointer with `p`. The
- * `factory` parameter will be used as the `CloneFactory` for future copies.
- * `p`: The pointer to take ownership of.
- * `factory`: The clone factory to use in future copies.
- * NOTE: It is not recommended to use this constructor, as the following is not exception safe
- * code:
- * ~~~
- * clonable_ptr<T, std::function<T* ()>> bad{new T, [](const T& p){ return p; }}; // BAD IDEA!!!
- * ~~~
- * Even if the above could be made exception safe, there are other more complicated use cases
- * which would not be exception safe. (The above is not exception safe, because the `new T`
- * expression can be evaluated before the lambda expression is evaluated and converted to a
- * `std::function`. The `std::function` constructor is allowed to throw, thus leaving `new T`
- * to be abandoned.
- */
- explicit inline clonable_ptr(T* const p, CloneFactory&& factory)
- : clonable_ptr{UniquePtr<T>{p}, std::move(factory), internal_construction{}} {
- static_assert(std::is_nothrow_move_constructible<CloneFactory>::value,
- "The `CloneFactory` type must be nothrow constructible to use as an r-value "
- "in an initialization expression with a raw pointer.");
- }
-
- /*!
- * Constructs a `clonable_ptr` by transferring ownership from `p` to `*this`. A default
- * `CloneFactory` will be provided for future copies.
- * `p`: The pointer to take ownership of.
- * NOTE: This constructor allows for implicit conversion from a `UniquePtr` (xvalue) object.
- * NOTE: This constructor is unavailable when `CloneFactory` is stateful.
- * NOTE: This usage should be preferred over the raw-pointer construction forms, when using
- * factories as constructor arguments, as in the following exception safe code:
- * ~~~
- * clonable_ptr<T, std::function<T* ()>> good{std::make_unique<T>(),
- * [](const T& p){ return p; }}; // GOOD IDEA!!!
- * ~~~
- */
- template <typename CloneFactory_ = CloneFactory,
- typename Derived,
- typename = typename std::enable_if<std::is_empty<CloneFactory_>::value>::type>
- inline clonable_ptr(UniquePtr<Derived> p) : data{CloneFactory{}, std::move(p)} {}
-
- /*!
- * Constructs a `clonable_ptr` by transferring ownership from `p` to `*this`. The `factory`
- * parameter will be used as the `CloneFactory` for future copies.
- * NOTE: This constructor allows for implicit conversion from a `UniquePtr` (xvalue) object.
- * `p`: The pointer to take ownership of.
- * `factory`: The clone factory to use in future copies.
- * NOTE: This usage should be preferred over the raw-pointer construction forms, when using
- * factories as constructor arguments, as in the following exception safe code:
- * ~~~
- * clonable_ptr<T, std::function<T* ()>> good{std::make_unique<T>(),
- * [](const T& p){ return p; }}; // GOOD IDEA!!!
- * ~~~
- */
- template <typename Derived>
- inline clonable_ptr(UniquePtr<Derived> p, CloneFactory factory)
- : data{std::move(factory), std::move(p)} {}
-
- /*!
- * Changes the value of this pointer, by creating a new object having the same value as `copy`.
- * The old object owned by `*this` will be deleted, and `*this` will manage a new copy of
- * `copy`, as created by `copy->clone()`. If `copy` is not managing anything (its internal
- * pointer is `nullptr`), then this new copy will also be nullptr.
- *
- * NOTE: This operation cannot be performed on an xvalue or prvalue instance. (This prevents
- * silliness such as: `func_returning_ptr()= some_other_func_returning_ptr();`)
- *
- * NOTE: `copy`'s `CloneFactory` will be used to copy.
- *
- * POST: `copy != nullptr ? copy != *this : copy == *this` -- If `copy` stores a pointer to a
- * value, then `*this` will have an independent pointer. If `copy` stores `nullptr`, then
- * `*this` will also store `nullptr`.
- *
- * `copy`: The value to make a copy of.
- * RETURNS: A reference to this pointer, after modification.
- */
- inline clonable_ptr& operator=(UniquePtr<T> copy) & {
- return *this = std::move(clonable_ptr{std::move(copy), this->cloneFactory()});
- }
-
- template <typename Derived>
- inline clonable_ptr& operator=(UniquePtr< Derived > copy) & {
- return *this = std::move(clonable_ptr{std::move(copy), this->cloneFactory()});
- }
-
- /*!
- * Change the `CloneFactory` for `*this` to `factory`.
- * NOTE: This operation cannot be performed on an xvalue or prvalue instance. (This prevents
- * silliness such as: `func_returning_ptr().setCloneFactory( factory );`.)
- */
- template <typename FactoryType>
- inline void setCloneFactory(FactoryType&& factory) & {
- this->cloneFactory() = std::forward<FactoryType>(factory);
- }
-
- /*!
- * Dereferences the pointer owned by `*this`.
- * NOTE: The behavior is undefined if `this->get() == nullptr`.
- * RETURNS: The object owned by `*this`, equivalent to `*get()`.
- */
- inline auto& operator*() const noexcept(noexcept(*this->ptr())) {
- return *this->ptr();
- }
-
- /*!
- * Dereferences the pointer owned by `*this`.
- * NOTE: The behavior is undefined if `this->get() == nullptr`.
- * RETURNS: A pointer to the object owned by `*this`, equivalent to `get()`.
- */
- inline auto* operator-> () const noexcept(noexcept(this->ptr().operator->())) {
- return this->ptr().operator->();
- }
-
- /*!
- * Returns `true` if `*this` owns a pointer to a value, and `false` otherwise.
- * RETURNS: A value equivalent to `static_cast< bool >( this->get() )`.
- */
- explicit inline operator bool() const noexcept {
- return this->ptr().get();
- }
-
- /*!
- * Converts `*this` to a `UniquePtr< T >` by transferring ownership. This function will retire
- * ownership of the pointer owned by `*this`. This is a safe operation, as this function cannot
- * be called from an lvalue context -- rvalue operations are used to represent transfer of
- * ownership semantics.
- *
- * NOTE: This function is only applicable in `rvalue` contexts.
- * NOTE: This function has transfer of ownership semantics.
- *
- * RETURNS: A `UniquePtr< T >` which owns the pointer formerly managed by `*this`.
- */
- inline operator UniquePtr<T>() && {
- return std::move(this->ptr());
- }
-
- /*! Provides a constant `UniquePtr< T >` view of the object owned by `*this`. */
- inline operator const UniquePtr<T>&() const& {
- return this->ptr();
- }
-
- /*! Provides a mutable `UniquePtr< T >` view of the object owned by `*this`. */
- inline operator UniquePtr<T>&() & {
- return this->ptr();
- }
-
- /*! Provides a C-style `T *` pointer to the object owned by `*this`. */
- inline T* get() const noexcept(noexcept(this->ptr().get())) {
- return this->ptr().get();
- }
-
- inline void reset() & noexcept {
- this->ptr().reset();
- }
-
- inline void reset(T* const p) & noexcept(noexcept(this->ptr().reset(p))) {
- this->ptr().reset(p);
- }
-
- // Equality
-
- template <typename C, typename F, template <typename, typename...> class U>
- inline friend bool operator==(const clonable_ptr<C, F, U>& lhs,
- const clonable_ptr<C, F, U>& rhs) {
- return lhs._makeEqualityLens() == rhs._makeEqualityLens();
- }
-
- template <typename C, typename F, template <typename, typename...> class U>
- inline friend bool operator==(const U<C>& lhs, const clonable_ptr<C, F, U>& rhs) {
- return lhs == rhs._makeEqualityLens();
- }
-
- template <typename C, typename F, template <typename, typename...> class U>
- inline friend bool operator==(const clonable_ptr<C, F, U>& lhs, const U<C>& rhs) {
- return lhs._makeEqualityLens() == rhs;
- }
-
- template <typename C, typename F, template <typename, typename...> class U>
- inline friend bool operator==(const std::nullptr_t& lhs, const clonable_ptr<C, F, U>& rhs) {
- return lhs == rhs._makeEqualityLens();
- }
-
- template <typename C, typename F, template <typename, typename...> class U>
- inline friend bool operator==(const clonable_ptr<C, F, U>& lhs, const std::nullptr_t& rhs) {
- return lhs._makeEqualityLens() == rhs;
- }
-
- // Strict weak order
-
- template <typename C, typename F, template <typename, typename...> class U>
- inline friend bool operator<(const clonable_ptr<C, F, U>& lhs,
- const clonable_ptr<C, F, U>& rhs) {
- return lhs._makeStrictWeakOrderLens() < rhs._makeStrictWeakOrderLens();
- }
-
- template <typename C, typename F, template <typename, typename...> class U>
- inline friend bool operator<(const U<C>& lhs, const clonable_ptr<C, F, U>& rhs) {
- return lhs < rhs._makeStrictWeakOrderLens();
- }
-
- template <typename C, typename F, template <typename, typename...> class U>
- inline friend bool operator<(const clonable_ptr<C, F, U>& lhs, const U<C>& rhs) {
- return lhs._makeStrictWeakOrderLens() < rhs;
- }
-
- template <typename C, typename F, template <typename, typename...> class U>
- inline friend bool operator<(const std::nullptr_t& lhs, const clonable_ptr<C, F, U>& rhs) {
- return lhs < rhs._makeStrictWeakOrderLens();
- }
-
- template <typename C, typename F, template <typename, typename...> class U>
- inline friend bool operator<(const clonable_ptr<C, F, U>& lhs, const std::nullptr_t& rhs) {
- return lhs._makeStrictWeakOrderLens() < rhs;
- }
-};
-
-// Inequality
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator!=(const clonable_ptr<C, F, U>& lhs, const clonable_ptr<C, F, U>& rhs) {
- return !(lhs == rhs);
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator!=(const U<C>& lhs, const clonable_ptr<C, F, U>& rhs) {
- return !(lhs == rhs);
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator!=(const clonable_ptr<C, F, U>& lhs, const U<C>& rhs) {
- return !(lhs == rhs);
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator!=(const std::nullptr_t& lhs, const clonable_ptr<C, F, U>& rhs) {
- return !(lhs == rhs);
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator!=(const clonable_ptr<C, F, U>& lhs, const std::nullptr_t& rhs) {
- return !(lhs == rhs);
-}
-
-// Greater than
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator>(const clonable_ptr<C, F, U>& lhs, const clonable_ptr<C, F, U>& rhs) {
- return rhs < lhs;
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator>(const U<C>& lhs, const clonable_ptr<C, F, U>& rhs) {
- return rhs < lhs;
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator>(const clonable_ptr<C, F, U>& lhs, const U<C>& rhs) {
- return rhs < lhs;
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator>(const std::nullptr_t& lhs, const clonable_ptr<C, F, U>& rhs) {
- return rhs < lhs;
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator>(const clonable_ptr<C, F, U>& lhs, const std::nullptr_t& rhs) {
- return rhs < lhs;
-}
-
-// Equal or Less
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator<=(const clonable_ptr<C, F, U>& lhs, const clonable_ptr<C, F, U>& rhs) {
- return !(lhs > rhs);
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator<=(const U<C>& lhs, const clonable_ptr<C, F, U>& rhs) {
- return !(lhs > rhs);
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator<=(const clonable_ptr<C, F, U>& lhs, const U<C>& rhs) {
- return !(lhs > rhs);
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator<=(const std::nullptr_t& lhs, const clonable_ptr<C, F, U>& rhs) {
- return !(lhs > rhs);
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator<=(const clonable_ptr<C, F, U>& lhs, const std::nullptr_t& rhs) {
- return !(lhs > rhs);
-}
-
-// Equal or greater
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator>=(const clonable_ptr<C, F, U>& lhs, const clonable_ptr<C, F, U>& rhs) {
- return !(lhs < rhs);
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator>=(const U<C>& lhs, const clonable_ptr<C, F, U>& rhs) {
- return !(lhs < rhs);
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator>=(const clonable_ptr<C, F, U>& lhs, const U<C>& rhs) {
- return !(lhs < rhs);
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator>=(const std::nullptr_t& lhs, const clonable_ptr<C, F, U>& rhs) {
- return !(lhs < rhs);
-}
-
-template <typename C, typename F, template <typename, typename...> class U>
-inline bool operator>=(const clonable_ptr<C, F, U>& lhs, const std::nullptr_t& rhs) {
- return !(lhs < rhs);
-}
-} // namespace mongo
diff --git a/src/mongo/base/clonable_ptr_test.cpp b/src/mongo/base/clonable_ptr_test.cpp
deleted file mode 100644
index 80b28b49d4d..00000000000
--- a/src/mongo/base/clonable_ptr_test.cpp
+++ /dev/null
@@ -1,954 +0,0 @@
-// clonable_ptr.t.cpp
-
-/*-
- * Copyright (C) 2016 MongoDB Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects
- * for all of the code used other than as permitted herein. If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so. If you do not
- * wish to do so, delete this exception statement from your version. If you
- * delete this exception statement from all source files in the program,
- * then also delete it in the license file.
- */
-
-#include "clonable_ptr.h"
-
-#include "mongo/stdx/memory.h"
-#include "mongo/unittest/unittest.h"
-
-#include <boost/lexical_cast.hpp>
-
-namespace {
-// These testing helper classes model various kinds of class which should be compatible with
-// `mongo::clonable_ptr`. The basic use cases satisfied by each class are described in each class's
-// documentation.
-
-// This class models the `Clonable` concept, and is used to test the simple case of `clonable_ptr`.
-class ClonableTest {
-private:
- std::string data =
- "This is the string data which is stored to make Functor Clonable need a complicated copy "
- "ctor.";
-
-public:
- std::unique_ptr<ClonableTest> clone() const {
- return mongo::stdx::make_unique<ClonableTest>();
- }
-};
-
-// This class provides a member structure which models `CloneFactory<AltClonableTest>`. The member
-// structure is available under the expected member name of `clone_factory_type`. The
-// `CloneFactory` is stateless.
-class AltClonableTest {
-private:
- std::string data =
- "This is the string data which is stored to make Functor Clonable need a complicated copy "
- "ctor.";
-
-public:
- struct clone_factory_type {
- std::unique_ptr<AltClonableTest> operator()(const AltClonableTest&) const {
- return mongo::stdx::make_unique<AltClonableTest>();
- }
- };
-};
-
-// This class requires a companion cloning function models `CloneFactory<Alt2ClonableTest>`. There
-// is an attendant specialization of the `mongo::clonable_traits` metafunction to provide the clone
-// factory for this type. That `CloneFactory` is stateless.
-class Alt2ClonableTest {
-private:
- std::string data =
- "This is the string data which is stored to make Functor Clonable need a complicated copy "
- "ctor.";
-};
-} // namespace
-
-namespace mongo {
-// This specialization of the `mongo::clonable_traits` metafunction provides a model of a stateless
-// `CloneFactory<Alt2ClonableTest>`
-template <>
-struct clonable_traits<::Alt2ClonableTest> {
- struct clone_factory_type {
- std::unique_ptr<Alt2ClonableTest> operator()(const Alt2ClonableTest&) const {
- return mongo::stdx::make_unique<Alt2ClonableTest>();
- }
- };
-};
-} // namespace mongo
-
-namespace {
-// This class uses a stateful cloning function provided by the `getCloningFunction` static member.
-// This stateful `CloneFactory<FunctorClonable>` must be passed to constructors of the
-// `cloning_ptr`.
-class FunctorClonable {
-private:
- std::string data =
- "This is the string data which is stored to make Functor Clonable need a complicated copy "
- "ctor.";
-
-public:
- using CloningFunctionType =
- std::function<std::unique_ptr<FunctorClonable>(const FunctorClonable&)>;
-
- static CloningFunctionType getCloningFunction() {
- return
- [](const FunctorClonable& c) { return mongo::stdx::make_unique<FunctorClonable>(c); };
- }
-};
-
-// This class uses a stateful cloning function provided by the `getCloningFunction` static member.
-// This stateful `CloneFactory<FunctorWithDynamicStateClonable>` must be passed to constructors of
-// the `cloning_ptr`. The `CloneFactory` for this type dynamically updates its internal state.
-// This is used to test cloning of objects that have dynamically changing clone factories.
-class FunctorWithDynamicStateClonable {
-private:
- std::string data =
- "This is the string data which is stored to make Functor Clonable need a complicated copy "
- "ctor.";
-
-public:
- FunctorWithDynamicStateClonable(const FunctorWithDynamicStateClonable&) = delete;
- FunctorWithDynamicStateClonable() = default;
-
- FunctorWithDynamicStateClonable(const std::string& s) : data(s) {}
-
- using CloningFunctionType = std::function<std::unique_ptr<FunctorWithDynamicStateClonable>(
- const FunctorWithDynamicStateClonable&)>;
-
- static CloningFunctionType getCloningFunction() {
- return [calls = 0](const FunctorWithDynamicStateClonable& c) mutable {
- return mongo::stdx::make_unique<FunctorWithDynamicStateClonable>(
- c.data + boost::lexical_cast<std::string>(++calls));
- };
- }
-};
-
-// This class models `Clonable`, with a return from clone which is
-// `Constructible<std::unique_ptr<RawPointerClonable>>` but isn't
-// `std::unique_ptr<RawPointerClonable>`. This is used to test that the `clonable_ptr` class does
-// not expect `RawPointerClonable::clone() const` to return a model of
-// `UniquePtr<RawPointerClonable>`
-class RawPointerClonable {
-public:
- RawPointerClonable* clone() const {
- return new RawPointerClonable;
- }
-};
-
-// This class models `Clonable`, with a return from clone which is
-// `Constructible<std::unique_ptr<UniquePtrClonable>>` because it is
-// `std::unique_ptr<UniquePtrClonable>`. This is used to test that the `clonable_ptr` class can
-// use a `UniquePtrClonable::clone() const` that returns a model of
-// `UniquePtr<UniquePtrClonable>`
-class UniquePtrClonable {
-public:
- std::unique_ptr<UniquePtrClonable> clone() const {
- return mongo::stdx::make_unique<UniquePtrClonable>();
- }
-};
-
-TEST(ClonablePtrTest, syntax_smoke_test) {
- {
- mongo::clonable_ptr<ClonableTest> p;
-
- p = mongo::stdx::make_unique<ClonableTest>();
-
- mongo::clonable_ptr<ClonableTest> p2 = p;
-
- ASSERT_TRUE(p != p2);
-
- static_assert(sizeof(p) == sizeof(ClonableTest*),
- "`mongo::clonable_ptr< T >` should be `sizeof` a pointer when there is no "
- "CloneFactory");
- }
-
- {
- mongo::clonable_ptr<AltClonableTest> p;
-
- p = mongo::stdx::make_unique<AltClonableTest>();
-
- mongo::clonable_ptr<AltClonableTest> p2 = p;
-
- ASSERT_TRUE(p != p2);
- }
-
- {
- mongo::clonable_ptr<Alt2ClonableTest> p;
-
- p = mongo::stdx::make_unique<Alt2ClonableTest>();
-
- mongo::clonable_ptr<Alt2ClonableTest> p2 = p;
-
- ASSERT_TRUE(p != p2);
- }
-
- {
- mongo::clonable_ptr<FunctorClonable, FunctorClonable::CloningFunctionType> p{
- FunctorClonable::getCloningFunction()};
-
- p = mongo::stdx::make_unique<FunctorClonable>();
-
- mongo::clonable_ptr<FunctorClonable, FunctorClonable::CloningFunctionType> p2 = p;
-
- ASSERT_TRUE(p != p2);
-
- mongo::clonable_ptr<FunctorClonable, FunctorClonable::CloningFunctionType> p3{
- FunctorClonable::getCloningFunction()};
-
- auto tmp = mongo::stdx::make_unique<FunctorClonable>();
- p3 = std::move(tmp);
-
- ASSERT_TRUE(p != p2);
- ASSERT_TRUE(p2 != p3);
- ASSERT_TRUE(p != p3);
- }
-}
-
-// These tests check that all expected valid syntactic forms of use for the
-// `mongo::clonable_ptr<Clonable>` are valid. These tests assert nothing but provide a single
-// unified place to check the syntax of this component. Build failures in these parts indicate that
-// a change to the component has broken an expected valid syntactic usage. Any expected valid usage
-// which is not in this list should be added.
-namespace SyntaxTests {
-template <typename Clonable>
-void construction() {
- // Test default construction
- { mongo::clonable_ptr<Clonable>{}; }
-
- // Test construction from a nullptr
- { mongo::clonable_ptr<Clonable>{nullptr}; }
-
- // Test construction from a Clonable pointer.
- {
- Clonable* const local = nullptr;
- mongo::clonable_ptr<Clonable>{local};
- }
-
- // Test move construction.
- { mongo::clonable_ptr<Clonable>{mongo::clonable_ptr<Clonable>{}}; }
-
- // Test copy construction.
- {
- mongo::clonable_ptr<Clonable> a;
- mongo::clonable_ptr<Clonable> b{a};
- }
-
- // Test move assignment.
- {
- mongo::clonable_ptr<Clonable> a;
- a = mongo::clonable_ptr<Clonable>{};
- }
-
- // Test copy assignment.
- {
- mongo::clonable_ptr<Clonable> a;
- mongo::clonable_ptr<Clonable> b;
- b = a;
- }
-
- // Test unique pointer construction
- { mongo::clonable_ptr<Clonable>{mongo::stdx::make_unique<Clonable>()}; }
-
- // Test unique pointer construction (conversion)
- {
- auto acceptor = [](const mongo::clonable_ptr<Clonable>&) {};
- acceptor(mongo::stdx::make_unique<Clonable>());
- }
-
- // Test non-conversion pointer construction
- { static_assert(!std::is_convertible<Clonable*, mongo::clonable_ptr<Clonable>>::value, ""); }
-
- // Test conversion unique pointer construction
- {
- static_assert(
- std::is_convertible<std::unique_ptr<Clonable>, mongo::clonable_ptr<Clonable>>::value,
- "");
- }
-}
-
-// Tests that syntactic forms that require augmented construction are proper
-template <typename Clonable, typename CloneFactory>
-void augmentedConstruction() {
- // Test default construction
- {
- static_assert(
- !std::is_default_constructible<mongo::clonable_ptr<Clonable, CloneFactory>>::value, "");
- }
-
- // Test Clone Factory construction
- { mongo::clonable_ptr<Clonable, CloneFactory>{Clonable::getCloningFunction()}; }
-
- // Test non-construction from a nullptr
- {
- static_assert(!std::is_constructible<mongo::clonable_ptr<Clonable, CloneFactory>,
- std::nullptr_t>::value,
- "");
- }
-
- // Test construction from a nullptr with factory
- { mongo::clonable_ptr<Clonable, CloneFactory>{nullptr, Clonable::getCloningFunction()}; }
-
- // Test construction from a Clonable pointer.
- {
- static_assert(
- !std::is_constructible<mongo::clonable_ptr<Clonable, CloneFactory>, Clonable*>::value,
- "");
- }
-
-
- // Test construction from a Clonable pointer with factory.
- {
- Clonable* const local = nullptr;
- mongo::clonable_ptr<Clonable, CloneFactory>{local, Clonable::getCloningFunction()};
- }
-
- // Test move construction.
- {
- mongo::clonable_ptr<Clonable, CloneFactory>{
- mongo::clonable_ptr<Clonable, CloneFactory>{Clonable::getCloningFunction()}};
- }
-
- // Test copy construction.
- {
- mongo::clonable_ptr<Clonable, CloneFactory> a{Clonable::getCloningFunction()};
- mongo::clonable_ptr<Clonable, CloneFactory> b{a};
- }
-
- // Test augmented copy construction.
- {
- mongo::clonable_ptr<Clonable, CloneFactory> a{Clonable::getCloningFunction()};
- mongo::clonable_ptr<Clonable, CloneFactory> b{a, Clonable::getCloningFunction()};
- }
-
-
- // Test move assignment.
- {
- mongo::clonable_ptr<Clonable, CloneFactory> a{Clonable::getCloningFunction()};
- a = mongo::clonable_ptr<Clonable, CloneFactory>{Clonable::getCloningFunction()};
- }
-
- // Test copy assignment.
- {
- mongo::clonable_ptr<Clonable, CloneFactory> a{Clonable::getCloningFunction()};
- mongo::clonable_ptr<Clonable, CloneFactory> b{Clonable::getCloningFunction()};
- b = a;
- }
-
- // Test unique pointer construction
- {
- mongo::clonable_ptr<Clonable, CloneFactory>{mongo::stdx::make_unique<Clonable>(),
- Clonable::getCloningFunction()};
- }
-
- // Test augmented unique pointer construction
- {
- mongo::clonable_ptr<Clonable, CloneFactory>{mongo::stdx::make_unique<Clonable>(),
- Clonable::getCloningFunction()};
- }
-
- // Test non-conversion pointer construction
- {
- static_assert(
- !std::is_convertible<Clonable*, mongo::clonable_ptr<Clonable, CloneFactory>>::value,
- "");
- Clonable* p = nullptr;
- mongo::clonable_ptr<Clonable, CloneFactory> x(p, CloneFactory{});
- }
-
- // Test conversion unique pointer construction
- {
- static_assert(!std::is_convertible<std::unique_ptr<Clonable>,
- mongo::clonable_ptr<Clonable, CloneFactory>>::value,
- "");
- }
-}
-
-template <typename Clonable>
-void pointerOperations() {
- mongo::clonable_ptr<Clonable> a;
-
- // Test `.get()` functionality:
- {
- Clonable* p = a.get();
- (void)p;
- }
-
- // Test `->` functionality
- {
- // We don't actually want to call the dtor, but we want the compiler to check that we
- // have.
- if (false) {
- a->~Clonable();
- }
- }
-
- // Test `*` functionality
- {
- Clonable& r = *a;
- (void)r;
- }
-
- // Test reset functionality
- {
- a.reset();
- a.reset(nullptr);
- a.reset(new Clonable);
- }
-}
-
-template <typename Clonable>
-void equalityOperations() {
- mongo::clonable_ptr<Clonable> a;
- mongo::clonable_ptr<Clonable> b;
-
- std::unique_ptr<Clonable> ua;
-
- // Test equality expressions
- {
- (void)(a == a);
- (void)(a == b);
- (void)(b == a);
-
- (void)(a == ua);
- (void)(ua == a);
-
- (void)(nullptr == a);
- (void)(a == nullptr);
- }
-
- // Test inequality expressions
- {
- (void)(a != a);
- (void)(a != b);
- (void)(b != a);
-
- (void)(a != ua);
- (void)(ua != a);
-
- (void)(nullptr == a);
- (void)(a == nullptr);
- }
-}
-} // namespace SyntaxTests
-
-TEST(ClonablePtrSyntaxTests, construction) {
- SyntaxTests::construction<ClonableTest>();
- SyntaxTests::construction<AltClonableTest>();
- SyntaxTests::construction<Alt2ClonableTest>();
- SyntaxTests::construction<RawPointerClonable>();
- SyntaxTests::construction<UniquePtrClonable>();
-}
-
-TEST(ClonablePtrSyntaxTests, augmentedConstruction) {
- SyntaxTests::augmentedConstruction<FunctorClonable, FunctorClonable::CloningFunctionType>();
- SyntaxTests::augmentedConstruction<FunctorWithDynamicStateClonable,
- FunctorWithDynamicStateClonable::CloningFunctionType>();
-}
-
-TEST(ClonablePtrSyntaxTests, pointerOperations) {
- SyntaxTests::pointerOperations<ClonableTest>();
- SyntaxTests::pointerOperations<AltClonableTest>();
- SyntaxTests::pointerOperations<Alt2ClonableTest>();
- SyntaxTests::pointerOperations<RawPointerClonable>();
- SyntaxTests::pointerOperations<UniquePtrClonable>();
-}
-
-TEST(ClonablePtrSyntaxTests, equalityOperations) {
- SyntaxTests::equalityOperations<ClonableTest>();
- SyntaxTests::equalityOperations<AltClonableTest>();
- SyntaxTests::equalityOperations<Alt2ClonableTest>();
- SyntaxTests::equalityOperations<RawPointerClonable>();
- SyntaxTests::equalityOperations<UniquePtrClonable>();
-}
-
-namespace BehaviorTests {
-class DetectDestruction {
-public:
- static int activeCount;
-
- static void resetCount() {
- activeCount = 0;
- }
-
- ~DetectDestruction() {
- --activeCount;
- }
-
- DetectDestruction(const DetectDestruction&) {
- ++activeCount;
- }
-
- DetectDestruction& operator=(const DetectDestruction&) = delete;
-
- DetectDestruction(DetectDestruction&&) = delete;
- DetectDestruction& operator=(DetectDestruction&&) = delete;
-
- DetectDestruction() {
- ++activeCount;
- }
-
- std::unique_ptr<DetectDestruction> clone() const {
- return mongo::stdx::make_unique<DetectDestruction>(*this);
- }
-};
-
-int DetectDestruction::activeCount = 0;
-
-struct DestructionGuard {
- DestructionGuard(const DestructionGuard&) = delete;
- DestructionGuard& operator=(const DestructionGuard&) = delete;
-
- DestructionGuard() {
- DetectDestruction::resetCount();
- }
-
- ~DestructionGuard() {
- ASSERT_EQ(DetectDestruction::activeCount, 0);
- }
-};
-
-TEST(ClonablePtrTest, basic_construction_test) {
- // Do not default construct the object
- {
- DestructionGuard check;
- mongo::clonable_ptr<DetectDestruction> p;
- ASSERT_EQ(DetectDestruction::activeCount, 0);
- }
-
- // Do not make unnecessary copies of the object from ptr
- {
- DestructionGuard check;
- mongo::clonable_ptr<DetectDestruction> p{new DetectDestruction};
- ASSERT_EQ(DetectDestruction::activeCount, 1);
- }
-
- // Do not make unnecessary copies of the object from unique_ptr
- {
- DestructionGuard check;
- mongo::clonable_ptr<DetectDestruction> p{mongo::stdx::make_unique<DetectDestruction>()};
- ASSERT_EQ(DetectDestruction::activeCount, 1);
- }
- {
- DestructionGuard check;
- mongo::clonable_ptr<DetectDestruction> p = mongo::stdx::make_unique<DetectDestruction>();
- ASSERT_EQ(DetectDestruction::activeCount, 1);
- }
-
- // Two separate constructions are unlinked
- {
- DestructionGuard check;
-
- mongo::clonable_ptr<DetectDestruction> p1{mongo::stdx::make_unique<DetectDestruction>()};
- ASSERT_EQ(DetectDestruction::activeCount, 1);
-
- {
- mongo::clonable_ptr<DetectDestruction> p2{
- mongo::stdx::make_unique<DetectDestruction>()};
- ASSERT_EQ(DetectDestruction::activeCount, 2);
- }
- ASSERT_EQ(DetectDestruction::activeCount, 1);
- }
-
- // Two separate constructions can have opposite order and be unlinked
- {
- DestructionGuard check;
-
- auto p1 = mongo::stdx::make_unique<mongo::clonable_ptr<DetectDestruction>>(
- mongo::stdx::make_unique<DetectDestruction>());
- ASSERT_EQ(DetectDestruction::activeCount, 1);
-
- auto p2 = mongo::stdx::make_unique<mongo::clonable_ptr<DetectDestruction>>(
- mongo::stdx::make_unique<DetectDestruction>());
- ASSERT_EQ(DetectDestruction::activeCount, 2);
-
- p1.reset();
- ASSERT_EQ(DetectDestruction::activeCount, 1);
-
- p2.reset();
- ASSERT_EQ(DetectDestruction::activeCount, 0);
- }
-}
-
-// TODO: Bring in an "equivalence class for equality predicate testing" framework.
-// Equals and Not Equals need to be tested independently -- It is not valid to assume that equals
-// and not equals are correctly implemented as complimentary predicates. Equality must be
-// reflexive, symmetric and transitive. This requres several instances that all have the same
-// value. Simply testing "2 == 2" and "3 != 2" is insufficient. Every combination of position and
-// equality must be tested to come out as expected.
-//
-// Consider that with equality it is important to make sure that `a == b` has the same meaning as `b
-// == a`. It is also necessary to check that `a == b` and `b == c` and `a == c` is true, when all
-// three are equal, and to do so in reverse: `b == a` and `c == b` and `c == a`. Further, the
-// relationships above have to hold for multiple cases. Similar cases need to be tested for
-// inequality.
-//
-// Further, equality is an incredibly important operation to test completely and thoroughly --
-// besides being a critical element in code using any value modeling type, it also is the keystone
-// in any testing schedule for a copyable and movable value type. Almost all testing of behavior
-// relies upon being able to detect fundamental differences in value. In order to provide this
-// correctly, we provide a full battery of tests for equality in all mathematically relevant
-// situations. For this equality testing schedule to be correct, we require a mechanism to
-// initialize objects (and references to those objects) which have predictable value. These
-// predictable values are then used to test known equality expressions for the correct evaluation.
-//
-// All other tests can then just use equality to verify that an object is in the desired state.
-// This greatly simplifies testing and also makes tests more precise.
-TEST(ClonablePtrTest, basicEqualityTest) {
- DestructionGuard check;
-
- mongo::clonable_ptr<DetectDestruction> n1;
- mongo::clonable_ptr<DetectDestruction> n2;
- mongo::clonable_ptr<DetectDestruction> n3;
-
- mongo::clonable_ptr<DetectDestruction> a = mongo::stdx::make_unique<DetectDestruction>();
- mongo::clonable_ptr<DetectDestruction> b = mongo::stdx::make_unique<DetectDestruction>();
- mongo::clonable_ptr<DetectDestruction> c = mongo::stdx::make_unique<DetectDestruction>();
-
- const mongo::clonable_ptr<DetectDestruction>& ap = a;
- const mongo::clonable_ptr<DetectDestruction>& bp = b;
- const mongo::clonable_ptr<DetectDestruction>& cp = c;
- const mongo::clonable_ptr<DetectDestruction>& ap2 = a;
- const mongo::clonable_ptr<DetectDestruction>& bp2 = b;
- const mongo::clonable_ptr<DetectDestruction>& cp2 = c;
-
- // Equals operator
-
- // Identity checks
-
- ASSERT(n1 == n1);
- ASSERT(n2 == n2);
- ASSERT(n3 == n3);
-
- ASSERT(a == a);
- ASSERT(b == b);
- ASSERT(c == c);
-
- // Same value checks. (Because unique pointers should never be the same value, we have to use
- // references.)
-
- ASSERT(n1 == n2);
- ASSERT(n1 == n3);
-
- ASSERT(n2 == n1);
- ASSERT(n2 == n3);
-
- ASSERT(n3 == n1);
- ASSERT(n3 == n2);
-
- ASSERT(a == ap);
- ASSERT(a == ap2);
- ASSERT(ap == a);
- ASSERT(ap == ap2);
- ASSERT(ap2 == a);
- ASSERT(ap2 == ap);
-
- ASSERT(b == bp);
- ASSERT(b == bp2);
- ASSERT(bp == b);
- ASSERT(bp == bp2);
- ASSERT(bp2 == b);
- ASSERT(bp2 == bp);
-
- ASSERT(c == cp);
- ASSERT(c == cp2);
- ASSERT(cp == c);
- ASSERT(cp == cp2);
- ASSERT(cp2 == c);
- ASSERT(cp2 == cp);
-
- // Different value checks:
-
- ASSERT(!(a == n1));
- ASSERT(!(b == n1));
- ASSERT(!(c == n1));
- ASSERT(!(a == n2));
- ASSERT(!(b == n2));
- ASSERT(!(c == n2));
-
- ASSERT(!(n1 == a));
- ASSERT(!(n1 == b));
- ASSERT(!(n1 == c));
- ASSERT(!(n2 == a));
- ASSERT(!(n2 == b));
- ASSERT(!(n2 == c));
-
- ASSERT(!(a == b));
- ASSERT(!(a == c));
-
- ASSERT(!(b == a));
- ASSERT(!(b == c));
-
- ASSERT(!(c == a));
- ASSERT(!(c == b));
-
- // Not Equals operator
-
- // Identity checks
-
- ASSERT(!(n1 != n1));
- ASSERT(!(n2 != n2));
- ASSERT(!(n3 != n3));
-
- ASSERT(!(a != a));
- ASSERT(!(b != b));
- ASSERT(!(c != c));
-
- // Same value checks. (Because unique pointers should never be the same value, we have to use
- // references.)
-
- ASSERT(!(n1 != n2));
- ASSERT(!(n1 != n3));
-
- ASSERT(!(n2 != n1));
- ASSERT(!(n2 != n3));
-
- ASSERT(!(n3 != n1));
- ASSERT(!(n3 != n2));
-
- ASSERT(!(a != ap));
- ASSERT(!(a != ap2));
- ASSERT(!(ap != a));
- ASSERT(!(ap != ap2));
- ASSERT(!(ap2 != a));
- ASSERT(!(ap2 != ap));
-
- ASSERT(!(b != bp));
- ASSERT(!(b != bp2));
- ASSERT(!(bp != b));
- ASSERT(!(bp != bp2));
- ASSERT(!(bp2 != b));
- ASSERT(!(bp2 != bp));
-
- ASSERT(!(c != cp));
- ASSERT(!(c != cp2));
- ASSERT(!(cp != c));
- ASSERT(!(cp != cp2));
- ASSERT(!(cp2 != c));
- ASSERT(!(cp2 != cp));
-
- // Different value checks:
-
- ASSERT(a != n1);
- ASSERT(b != n1);
- ASSERT(c != n1);
- ASSERT(a != n2);
- ASSERT(b != n2);
- ASSERT(c != n2);
-
- ASSERT(n1 != a);
- ASSERT(n1 != b);
- ASSERT(n1 != c);
- ASSERT(n2 != a);
- ASSERT(n2 != b);
- ASSERT(n2 != c);
-
- ASSERT(a != b);
- ASSERT(a != c);
-
- ASSERT(b != a);
- ASSERT(b != c);
-
- ASSERT(c != a);
- ASSERT(c != b);
-}
-
-// TODO: all other forms of equality with other types (`std::nullptr_t` and `std::unique_ptr< T >`)
-// need testing still.
-
-TEST(ClonablePtrTest, ownershipStabilityTest) {
- {
- DestructionGuard check;
-
- auto ptr_init = mongo::stdx::make_unique<DetectDestruction>();
- const auto* rp = ptr_init.get();
-
- mongo::clonable_ptr<DetectDestruction> cp = std::move(ptr_init);
-
- ASSERT(rp == cp.get());
-
- mongo::clonable_ptr<DetectDestruction> cp2 = std::move(cp);
-
- ASSERT(rp == cp2.get());
-
- mongo::clonable_ptr<DetectDestruction> cp3;
-
- ASSERT(nullptr == cp3);
-
- cp3 = std::move(cp2);
-
- ASSERT(rp == cp3.get());
- }
-
- {
- auto ptr_init = mongo::stdx::make_unique<DetectDestruction>();
- const auto* rp = ptr_init.get();
-
- mongo::clonable_ptr<DetectDestruction> cp{ptr_init.release()};
-
- ASSERT(rp == cp.get());
-
- mongo::clonable_ptr<DetectDestruction> cp2 = std::move(cp);
-
- ASSERT(rp == cp2.get());
-
- mongo::clonable_ptr<DetectDestruction> cp3;
-
- ASSERT(nullptr == cp3.get());
-
- cp3 = std::move(cp2);
-
- ASSERT(rp == cp3.get());
- }
-}
-
-class ClonableObject {
-private:
- int value = 0;
-
-public:
- // ClonableObject( const ClonableObject & ) { abort(); }
- ClonableObject() = default;
- explicit ClonableObject(const int v) : value(v) {}
-
- std::unique_ptr<ClonableObject> clone() const {
- return mongo::stdx::make_unique<ClonableObject>(*this);
- }
-
- auto make_equality_lens() const -> decltype(std::tie(this->value)) {
- return std::tie(value);
- }
-};
-
-bool operator==(const ClonableObject& lhs, const ClonableObject& rhs) {
- return lhs.make_equality_lens() == rhs.make_equality_lens();
-}
-
-bool operator!=(const ClonableObject& lhs, const ClonableObject& rhs) {
- return !(lhs == rhs);
-}
-
-TEST(ClonablePtrTest, noObjectCopySemanticTest) {
- mongo::clonable_ptr<ClonableObject> p;
-
- mongo::clonable_ptr<ClonableObject> p2 = p;
- ASSERT(p == p2);
-
- mongo::clonable_ptr<ClonableObject> p3;
-
- p3 = p;
- ASSERT(p == p3);
-}
-
-TEST(ClonablePtrTest, objectCopySemanticTest) {
- mongo::clonable_ptr<ClonableObject> p = mongo::stdx::make_unique<ClonableObject>(1);
- mongo::clonable_ptr<ClonableObject> q = mongo::stdx::make_unique<ClonableObject>(2);
- ASSERT(p != q);
- ASSERT(*p != *q);
-
- mongo::clonable_ptr<ClonableObject> p2 = p;
- ASSERT(p != p2);
- ASSERT(*p == *p2);
-
- mongo::clonable_ptr<ClonableObject> q2 = q;
- ASSERT(q2 != q);
- ASSERT(q2 != p);
- ASSERT(q2 != p2);
- ASSERT(*q2 == *q);
-
- q2 = p2;
- ASSERT(q2 != q);
- ASSERT(q2 != p);
- ASSERT(q2 != p2);
- ASSERT(*q2 == *p2);
-}
-
-class Interface {
-public:
- virtual ~Interface() = default;
- virtual void consumeText(const std::string& message) = 0;
- virtual std::string produceText() = 0;
-
- std::unique_ptr<Interface> clone() const {
- return std::unique_ptr<Interface>{this->clone_impl()};
- }
-
-private:
- virtual Interface* clone_impl() const = 0;
-};
-
-class GeneratorImplementation : public Interface {
-private:
- const std::string root;
- int generation = 0;
-
- GeneratorImplementation* clone_impl() const {
- return new GeneratorImplementation{*this};
- }
-
-public:
- explicit GeneratorImplementation(const std::string& m) : root(m) {}
-
- void consumeText(const std::string&) override {}
-
- std::string produceText() override {
- return root + boost::lexical_cast<std::string>(++generation);
- }
-};
-
-class StorageImplementation : public Interface {
-private:
- std::string store;
-
- StorageImplementation* clone_impl() const {
- return new StorageImplementation{*this};
- }
-
-public:
- void consumeText(const std::string& m) override {
- store = m;
- }
- std::string produceText() override {
- return store;
- }
-};
-
-
-TEST(ClonablePtrSimpleTest, simpleUsageExample) {
- mongo::clonable_ptr<Interface> source;
- mongo::clonable_ptr<Interface> sink;
-
- mongo::clonable_ptr<Interface> instance = std::make_unique<StorageImplementation>();
-
- sink = instance;
-
- ASSERT(instance.get() != sink.get());
-
- instance = std::make_unique<GeneratorImplementation>("base message");
-
-
- source = std::move(instance);
-
-
- sink->consumeText(source->produceText());
-}
-
-} // namespace BehaviorTests
-} // namespace
diff --git a/src/mongo/base/concept/README b/src/mongo/base/concept/README
deleted file mode 100644
index bc2c74fabe4..00000000000
--- a/src/mongo/base/concept/README
+++ /dev/null
@@ -1,5 +0,0 @@
-This directory contains a number of C++ headers which describe concepts for
-C++ types used by and with the Mongo library. These headers do not describe
-instantiable types, but instead are used to concisely describe models of C++
-type concepts. When C++ grows a proper `Concepts` feature, these files can be
-converted to proper concepts.
diff --git a/src/mongo/base/concept/assignable.h b/src/mongo/base/concept/assignable.h
deleted file mode 100644
index 8cf3f0e9ab5..00000000000
--- a/src/mongo/base/concept/assignable.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-#include "mongo/base/concept/copy_assignable.h"
-#include "mongo/base/concept/copy_constructible.h"
-
-namespace mongo {
-namespace concept {
-/*!
- * The Assignable concept models a type which can be copy assigned and copy constructed.
- */
-struct Assignable : CopyConstructible, CopyAssignable {};
-} // namespace concept
-} // namespace mongo
diff --git a/src/mongo/base/concept/clonable.h b/src/mongo/base/concept/clonable.h
deleted file mode 100644
index 96354333c0d..00000000000
--- a/src/mongo/base/concept/clonable.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-#include "mongo/base/concept/constructible.h"
-#include "mongo/base/concept/unique_ptr.h"
-
-namespace mongo {
-namespace concept {
-/*!
- * Objects conforming to the Clonable concept can be dynamically copied, using `this->clone()`.
- * The Clonable concept does not specify the return type of the `clone()` function.
- */
-struct Clonable {
- /*! Clonable objects must be safe to destroy, by pointer. */
- virtual ~Clonable() noexcept = 0;
-
- /*! Clonable objects can be cloned without knowing the actual dynamic type. */
- Constructible<UniquePtr<Clonable>> clone() const;
-};
-} // namespace concept
-} // namespace mongo
diff --git a/src/mongo/base/concept/clone_factory.h b/src/mongo/base/concept/clone_factory.h
deleted file mode 100644
index 17e7be07cc3..00000000000
--- a/src/mongo/base/concept/clone_factory.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-
-#include "mongo/base/concept/assignable.h"
-#include "mongo/base/concept/constructible.h"
-#include "mongo/base/concept/unique_ptr.h"
-
-namespace mongo {
-namespace concept {
-/*!
- * Objects conforming to the `CloneFactory` concept are function-like constructs which return
- * objects that are dynamically allocated copies of their inputs.
- * These copies can be made without knowing the actual dynamic type. The `CloneFactory` type itself
- * must be `Assignable`, in that it can be used with automatically generated copy constructors and
- * copy assignment operators.
- */
-template <typename T>
-struct CloneFactory : Assignable {
- Constructible<UniquePtr<T>> operator()(const T*) const;
-};
-} // namespace concept
-} // namespace mongo
diff --git a/src/mongo/base/concept/constructible.h b/src/mongo/base/concept/constructible.h
deleted file mode 100644
index b6e5211e6f1..00000000000
--- a/src/mongo/base/concept/constructible.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma once
-
-#include <type_traits>
-
-#include "mongo/stdx/type_traits.h"
-
-namespace mongo {
-namespace concept {
-
-/**
- * The Constructable trait indicates whether `T` is constructible from `Constructible`.
- *
- * RETURNS: true if `T{ std::declval< Constructible >() }` is a valid expression and false
- * otherwise.
- */
-template <typename T, typename Constructible, typename = void>
-struct is_constructible : std::false_type {};
-
-template <typename T, typename Constructible>
-struct is_constructible<T,
- Constructible,
- stdx::void_t<decltype(T{std::declval<Constructible<T>>()})>>
- : std::true_type {};
-
-/**
- * The Constructable concept models a type which can be passed to a single-argument constructor of
- * `T`.
- * This is not possible to describe in the type `Constructible`.
- *
- * The expression: `T{ std::declval< Constructible< T > >() }` should be valid.
- *
- * This concept is more broadly applicable than `ConvertibleTo`. `ConvertibleTo` uses implicit
- * conversion, whereas `Constructible` uses direct construction.
- */
-template <typename T>
-struct Constructible {};
-} // namespace concept
-} // namespace mongo
diff --git a/src/mongo/base/concept/convertible_to.h b/src/mongo/base/concept/convertible_to.h
deleted file mode 100644
index 57e733418cf..00000000000
--- a/src/mongo/base/concept/convertible_to.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#pragma once
-
-namespace mongo {
-namespace concept {
-/**
- * The ConvertibleTo concept models a type which can be converted implicitly into a `T`.
- * The code: `T x; x= ConvertibleTo< T >{};` should be valid.
- */
-template <typename T>
-struct ConvertibleTo {
- operator T();
-}
-} // namespace concept
-} // namespace mongo
diff --git a/src/mongo/base/concept/copy_assignable.h b/src/mongo/base/concept/copy_assignable.h
deleted file mode 100644
index 2b29e96eb82..00000000000
--- a/src/mongo/base/concept/copy_assignable.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma once
-
-namespace mongo {
-namespace concept {
-/**
- * The CopyAssignable concept models a type which can be copy assigned.
- *
- * The expression: `copyAssignable= copyAssignable` should be valid.
- */
-struct CopyAssignable {
- /**
- * The copy assignment operator is required by `CopyAssignable`.
- * NOTE: Copy Assignment is only required on lvalue targets of `CopyAssignable`.
- */
- CopyAssignable& operator=(const CopyAssignable&) &;
-};
-} // namespace concept
-} // namespace mongo
diff --git a/src/mongo/base/concept/copy_constructible.h b/src/mongo/base/concept/copy_constructible.h
deleted file mode 100644
index c96856cc485..00000000000
--- a/src/mongo/base/concept/copy_constructible.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#pragma once
-
-namespace mongo {
-namespace concept {
-/**
- * The CopyConstructable concept models a type which can be copy constructed.
- *
- * The expression: `CopyConstructible{ copyConstructible }` should be valid.
- */
-struct CopyConstructible {
- CopyConstructible(const CopyConstructible&);
-};
-} // namespace concept
-} // namespace mongo
diff --git a/src/mongo/base/concept/unique_ptr.h b/src/mongo/base/concept/unique_ptr.h
deleted file mode 100644
index 1edd552a93f..00000000000
--- a/src/mongo/base/concept/unique_ptr.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#pragma once
-
-#include "mongo/base/concept/convertible_to.h"
-
-namespace mongo {
-namespace concept {
-/**
- * The `UniquePtr` Concept models a movable owning pointer of an object.
- * `std::unique_ptr< T >` is a model of `mongo::concept::UniquePtr< T >`.
- */
-template <typename T>
-struct UniquePtr {
- /** The `UniquePtr< T >` must retire its pointer to `T` on destruction. */
- ~UniquePtr() noexcept;
-
- UniquePtr(UniquePtr&& p);
- UniquePtr& operator=(UniquePtr&& p);
-
- UniquePtr();
- UniquePtr(T* p);
-
- ConvertibleTo<T*> operator->() const;
- T& operator*() const;
-
- explicit operator bool() const;
-
- ConvertibleTo<T*> get() const;
-
- void reset() noexcept;
- void reset(ConvertibleTo<T*>);
-};
-
-/*! A `UniquePtr` object must be equality comparable. */
-template <typename T>
-bool operator==(const UniquePtr<T>& lhs, const UniquePtr<T>& rhs);
-
-/*! A `UniquePtr` object must be inequality comparable. */
-template <typename T>
-bool operator!=(const UniquePtr<T>& lhs, const UniquePtr<T>& rhs);
-} // namespace concept
-} // namespace mongo