From 113aec14763aefe674d8f87bf2dfc784fdce655a Mon Sep 17 00:00:00 2001 From: Ezra Chung Date: Tue, 30 Jul 2024 14:47:13 -0500 Subject: [PATCH 01/13] Formatting --- src/mongocxx/test/collection.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mongocxx/test/collection.cpp b/src/mongocxx/test/collection.cpp index a151f4c6b1..7a6c549150 100644 --- a/src/mongocxx/test/collection.cpp +++ b/src/mongocxx/test/collection.cpp @@ -2154,10 +2154,10 @@ TEST_CASE("read_concern is inherited from parent", "[collection]") { } } -void find_index_and_validate( - collection& coll, - stdx::string_view index_name, - const std::function& validate = [](bsoncxx::document::view) {}) { +void find_index_and_validate(collection& coll, + stdx::string_view index_name, + const std::function& validate = + [](bsoncxx::document::view) {}) { auto cursor = coll.list_indexes(); for (auto&& index : cursor) { From ab85f8268d8a2b97d7b871b3cc7b2af467bc3ceb Mon Sep 17 00:00:00 2001 From: Ezra Chung Date: Tue, 30 Jul 2024 14:45:29 -0500 Subject: [PATCH 02/13] Address -Wzero-as-null-pointer-constant warnings --- src/bsoncxx/test/catch.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bsoncxx/test/catch.hh b/src/bsoncxx/test/catch.hh index 3add50987a..859c9b96e3 100644 --- a/src/bsoncxx/test/catch.hh +++ b/src/bsoncxx/test/catch.hh @@ -99,9 +99,9 @@ struct StringMaker> { template <> struct StringMaker { static std::string convert(bsoncxx::detail::strong_ordering o) { - if (o < 0) { + if (o < nullptr) { return "[less-than]"; - } else if (o > 0) { + } else if (o > nullptr) { return "[greater-than]"; } else { return "[equal/equivalent]"; From 7e467c8ecee994672893ab63898d0075a84d5564 Mon Sep 17 00:00:00 2001 From: Ezra Chung Date: Wed, 31 Jul 2024 11:23:52 -0500 Subject: [PATCH 03/13] Address -Wundef warnings --- src/bsoncxx/test/string_view.test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bsoncxx/test/string_view.test.cpp b/src/bsoncxx/test/string_view.test.cpp index a92d53fc2a..b9ca5874bf 100644 --- a/src/bsoncxx/test/string_view.test.cpp +++ b/src/bsoncxx/test/string_view.test.cpp @@ -10,7 +10,7 @@ #endif #endif -#if __cpp_lib_string_view +#if defined(__cpp_lib_string_view) #include #endif From 6384d80641257989884ec0bd5067da4480638dbb Mon Sep 17 00:00:00 2001 From: Ezra Chung Date: Wed, 31 Jul 2024 13:01:45 -0500 Subject: [PATCH 04/13] Restrict Doxygen examples to examples/ --- Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doxyfile b/Doxyfile index 3a3d9ce66d..cfd1f33dcd 100644 --- a/Doxyfile +++ b/Doxyfile @@ -938,7 +938,7 @@ EXCLUDE_SYMBOLS = bsoncxx::detail \ # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = . +EXAMPLE_PATH = examples # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and From 015851ab2cf6c8748183f25906c38f146bd93a79 Mon Sep 17 00:00:00 2001 From: Ezra Chung Date: Tue, 30 Jul 2024 14:29:34 -0500 Subject: [PATCH 05/13] Fix Doxygen docs and parsing in stdx and config headers --- Doxyfile | 3 +- .../bsoncxx/v_noabi/bsoncxx/config/util.hpp | 146 ++++----- .../v_noabi/bsoncxx/stdx/make_unique.hpp | 8 +- .../v_noabi/bsoncxx/stdx/operators.hpp | 91 +++--- .../bsoncxx/v_noabi/bsoncxx/stdx/optional.hpp | 192 ++++++------ .../v_noabi/bsoncxx/stdx/string_view.hpp | 170 ++--------- .../v_noabi/bsoncxx/stdx/type_traits.hpp | 278 ++++++++---------- src/bsoncxx/test/optional.test.cpp | 2 +- src/bsoncxx/test/type_traits.test.cpp | 6 +- 9 files changed, 336 insertions(+), 560 deletions(-) diff --git a/Doxyfile b/Doxyfile index cfd1f33dcd..e62228d93d 100644 --- a/Doxyfile +++ b/Doxyfile @@ -901,8 +901,7 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/operators.hpp \ - src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/type_traits.hpp +EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded diff --git a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/config/util.hpp b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/config/util.hpp index c12caac094..239dc09405 100644 --- a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/config/util.hpp +++ b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/config/util.hpp @@ -1,34 +1,24 @@ -// clang-format off -/** - * @internal - * @brief Convert the given macro argument to a string literal, after macro expansion - */ +// Convert the given macro argument to a string literal, after macro expansion. #define BSONCXX_STRINGIFY(...) BSONCXX_STRINGIFY_IMPL(__VA_ARGS__) #define BSONCXX_STRINGIFY_IMPL(...) #__VA_ARGS__ -/** - * @internal - * @brief Token-paste two macro arguments, after macro expansion - */ +// Token-paste two macro arguments, after macro expansion #define BSONCXX_CONCAT(A, ...) BSONCXX_CONCAT_IMPL(A, __VA_ARGS__) #define BSONCXX_CONCAT_IMPL(A, ...) A##__VA_ARGS__ -/** - * @internal - * @brief Expands to a _Pragma() preprocessor directive, after macro expansion - * - * The arguments an arbitrary "token soup", and should not be quoted like a regular - * _Pragma. This macro will stringify-them itself. - * - * Example: - * - * BSONCXX_PRAGMA(GCC diagnostic ignore "-Wconversion") - * - * will become: - * - * _Pragma("GCC diagnostic ignore \"-Wconversion\"") - * - */ +// Expands to a _Pragma() preprocessor directive, after macro expansion +// +// The arguments an arbitrary "token soup", and should not be quoted like a regular +// _Pragma. This macro will stringify-them itself. +// +// Example: +// +// BSONCXX_PRAGMA(GCC diagnostic ignore "-Wconversion") +// +// will become: +// +// _Pragma("GCC diagnostic ignore \"-Wconversion\"") +// #define BSONCXX_PRAGMA(...) _bsoncxxPragma(__VA_ARGS__) #ifdef _MSC_VER // Old MSVC doesn't recognize C++11 _Pragma(), but it always recognized __pragma @@ -37,87 +27,69 @@ #define _bsoncxxPragma(...) _Pragma(BSONCXX_STRINGIFY(__VA_ARGS__)) #endif -/** - * @internal - * @brief Use in a declaration position to force the appearence of a semicolon - * as the next token. Use this for statement-like or declaration-like macros to - * enforce that their call sites are followed by a semicolon - */ +// Use in a declaration position to force the appearence of a semicolon +// as the next token. Use this for statement-like or declaration-like macros to +// enforce that their call sites are followed by a semicolon #define BSONCXX_FORCE_SEMICOLON static_assert(true, "") -/** - * @internal - * @brief Add a trailing noexcept, decltype-return, and return-body to a - * function definition. (Not compatible with lambda expressions.) - * - * Example: - * - * template - * auto foo(T x, T y) BSONCXX_RETURNS(x + y); - * - * Becomes: - * - * template - * auto foo(T x, T y) noexcept(noexcept(x + y)) - * -> decltype(x + y) - * { return x + y }; - * - */ +// Add a trailing noexcept, decltype-return, and return-body to a +// function definition. (Not compatible with lambda expressions.) +// +// Example: +// +// template +// auto foo(T x, T y) BSONCXX_RETURNS(x + y); +// +// Becomes: +// +// template +// auto foo(T x, T y) noexcept(noexcept(x + y)) +// -> decltype(x + y) +// { return x + y }; +// #define BSONCXX_RETURNS(...) \ noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) { \ return __VA_ARGS__; \ } \ BSONCXX_FORCE_SEMICOLON -/** - * @internal - * @macro mongocxx_cxx14_constexpr - * @brief Expands to `constexpr` if compiling as c++14 or greater, otherwise - * expands to `inline`. - * - * Use this on functions that can only be constexpr in C++14 or newer, including - * non-const member functions. - */ +// @macro mongocxx_cxx14_constexpr +// Expands to `constexpr` if compiling as c++14 or greater, otherwise +// expands to `inline`. +// +// Use this on functions that can only be constexpr in C++14 or newer, including +// non-const member functions. #if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L && _MSC_VER > 1910) #define bsoncxx_cxx14_constexpr constexpr #else #define bsoncxx_cxx14_constexpr inline #endif -/** - * @internal - * @brief Disable a warning for a particular compiler. - * - * The argument should be of the form: - * - * - Clang() - * - GCC() - * - GNU() - * - MSVC() - * - * The "GNU" form applies to both GCC and Clang - */ -#define BSONCXX_DISABLE_WARNING(Spec) \ +// Disable a warning for a particular compiler. +// +// The argument should be of the form: +// +// - Clang() +// - GCC() +// - GNU() +// - MSVC() +// +// The "GNU" form applies to both GCC and Clang +#define BSONCXX_DISABLE_WARNING(Spec) \ BSONCXX_CONCAT(_bsoncxxDisableWarningImpl_for_, Spec) \ BSONCXX_FORCE_SEMICOLON -/** - * @internal - * @brief Push the current compiler diagnostics settings state - */ -#define BSONCXX_PUSH_WARNINGS() \ +// Push the current compiler diagnostics settings state +#define BSONCXX_PUSH_WARNINGS() \ BSONCXX_IF_GNU_LIKE(BSONCXX_PRAGMA(GCC diagnostic push)) \ - BSONCXX_IF_MSVC(BSONCXX_PRAGMA(warning(push))) \ + BSONCXX_IF_MSVC(BSONCXX_PRAGMA(warning(push))) \ BSONCXX_FORCE_SEMICOLON -/** - * @internal - * @brief Restore prior compiler diagnostics settings from before the most - * recent BSONCXX_PUSH_WARNINGS() - */ -#define BSONCXX_POP_WARNINGS() \ +// Restore prior compiler diagnostics settings from before the most +// recent BSONCXX_PUSH_WARNINGS() +#define BSONCXX_POP_WARNINGS() \ BSONCXX_IF_GNU_LIKE(BSONCXX_PRAGMA(GCC diagnostic pop)) \ - BSONCXX_IF_MSVC(BSONCXX_PRAGMA(warning(pop))) \ + BSONCXX_IF_MSVC(BSONCXX_PRAGMA(warning(pop))) \ BSONCXX_FORCE_SEMICOLON #define _bsoncxxDisableWarningImpl_for_GCC(...) \ @@ -126,9 +98,9 @@ #define _bsoncxxDisableWarningImpl_for_Clang(...) \ BSONCXX_IF_CLANG(BSONCXX_PRAGMA(GCC diagnostic ignored __VA_ARGS__)) -#define _bsoncxxDisableWarningImpl_for_GNU(...) \ +#define _bsoncxxDisableWarningImpl_for_GNU(...) \ _bsoncxxDisableWarningImpl_for_GCC(__VA_ARGS__) \ - _bsoncxxDisableWarningImpl_for_Clang(__VA_ARGS__) + _bsoncxxDisableWarningImpl_for_Clang(__VA_ARGS__) #define _bsoncxxDisableWarningImpl_for_MSVC(...) \ BSONCXX_IF_MSVC(BSONCXX_PRAGMA(warning(disable : __VA_ARGS__))) diff --git a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/make_unique.hpp b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/make_unique.hpp index 36aeb4f7e7..14a519b1e5 100644 --- a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/make_unique.hpp +++ b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/make_unique.hpp @@ -112,7 +112,7 @@ namespace stdx { using ::std::make_unique; #else -/// Equivalent to `std::make_unique(args...)` where `T` is a non-array type. +// Equivalent to `std::make_unique(args...)` where `T` is a non-array type. template , @@ -123,7 +123,7 @@ std::unique_ptr make_unique(Args&&... args) { return Impl::make(std::true_type{}, std::forward(args)...); } -/// Equivalent to `std::make_unique(count)` where `T` is an array type. +// Equivalent to `std::make_unique(count)` where `T` is an array type. template < typename T, typename Impl = detail::make_unique_impl, @@ -142,7 +142,7 @@ std::unique_ptr make_unique(std::size_t count) { using ::std::make_unique_for_overwrite; #else -/// Equivalent to `std::make_unique_for_overwrite()` where `T` is a non-array type. +// Equivalent to `std::make_unique_for_overwrite()` where `T` is a non-array type. template , typename std::enable_if::value, @@ -151,7 +151,7 @@ std::unique_ptr make_unique_for_overwrite() { return Impl::make(std::false_type{}); } -/// Equivalent to `std::make_unique_for_overwrite(count)` where `T` is an array type. +// Equivalent to `std::make_unique_for_overwrite(count)` where `T` is an array type. template < typename T, typename Impl = detail::make_unique_impl, diff --git a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/operators.hpp b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/operators.hpp index 756c9e6cbb..2ea93c6e6d 100644 --- a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/operators.hpp +++ b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/operators.hpp @@ -28,27 +28,23 @@ namespace detail { template auto is_equality_comparable_f(...) -> std::false_type; +BSONCXX_PUSH_WARNINGS(); +BSONCXX_DISABLE_WARNING(GNU("-Wfloat-equal")); template -auto is_equality_comparable_f(int, - bool b = false, - const_reference_t l = soft_declval(), - const_reference_t r = soft_declval()) - -> true_t; - -/** - * @brief Detect whether two types are equality-comparable. - * - * Requires L == R, L != R, R == L, and R != L - */ +auto is_equality_comparable_f(int, bool b = false) + -> true_t() == std::declval()) ? 0 : 0, // + (std::declval() == std::declval()) ? 0 : 0, + (std::declval() != std::declval()) ? 0 : 0, + (std::declval() != std::declval()) ? 0 : 0)>; +BSONCXX_POP_WARNINGS(); + +// Detect whether two types are equality-comparable. +// +// Requires L == R, L != R, R == L, and R != L. template struct is_equality_comparable : decltype(is_equality_comparable_f(0)) {}; -/** - * @brief Callable object and tag type for equality comparison - */ +// Callable object and tag type for equality comparison. struct equal_to { template constexpr requires_t> // @@ -57,10 +53,8 @@ struct equal_to { } }; -/** - * @brief Derive from this class to define ADL-only operator== and operator!= on the basis of - * an ADL-only tag_invoke(equal_to, l, r) - */ +// Derive from this class to define ADL-only operator== and operator!= on the basis of +// an ADL-only tag_invoke(equal_to, l, r). class equality_operators { template constexpr static auto impl(rank<1>, L& l, R& r) BSONCXX_RETURNS(tag_invoke(equal_to{}, l, r)); @@ -68,20 +62,22 @@ class equality_operators { template constexpr static auto impl(rank<0>, L& l, R& r) BSONCXX_RETURNS(tag_invoke(equal_to{}, r, l)); + // @cond DOXYGEN_DISABLE "Found ';' while parsing initializer list!" template constexpr friend auto operator==(const Left& self, const Other& other) BSONCXX_RETURNS(equality_operators::impl(rank<1>{}, self, other)); + // @endcond + // @cond DOXYGEN_DISABLE "Found ';' while parsing initializer list!" template constexpr friend auto operator!=(const Left& self, const Other& other) BSONCXX_RETURNS(!equality_operators::impl(rank<1>{}, self, other)); + // @endcond }; -/** - * @brief Very basic impl of C++20 std::strong_ordering - * - * We don't need other weaker orderings yet, so this is all that we have - */ +// Very basic impl of C++20 std::strong_ordering. +// +// We don't need other weaker orderings yet, so this is all that we have. class strong_ordering { signed char _c; struct _construct {}; @@ -136,12 +132,12 @@ INLINE_VAR const strong_ordering strong_ordering::equal = #pragma pop_macro("INLINE_VAR") -/** - * @brief Implements a three-way comparison between two objects. That is, in - * a single operation, determine whether the left operand is less-than, greater-than, - * or equal-to the right-hand operand. - */ +// Implements a three-way comparison between two objects. That is, in +// a single operation, determine whether the left operand is less-than, greater-than, +// or equal-to the right-hand operand. struct compare_three_way { + BSONCXX_PUSH_WARNINGS(); + BSONCXX_DISABLE_WARNING(GNU("-Wfloat-equal")); template () < std::declval()), @@ -151,6 +147,7 @@ struct compare_three_way { : (l == r ? strong_ordering::equal // : strong_ordering::greater); } + BSONCXX_POP_WARNINGS(); template {})); }; -/** - * @brief Inherit to define ADL-visible ordering operators based on an ADL-visible - * implementation of tag_invoke(compare_three_way, l, r) - */ +// Inherit to define ADL-visible ordering operators based on an ADL-visible +// implementation of tag_invoke(compare_three_way, l, r). struct ordering_operators { template constexpr static auto impl(const L& l, const R& r, rank<1>) @@ -183,7 +178,7 @@ struct ordering_operators { #define DEFOP(Oper) \ template \ constexpr friend auto operator Oper(const L& l, const R& r) \ - BSONCXX_RETURNS(ordering_operators::impl(l, r, rank<1>{}) Oper 0) + BSONCXX_RETURNS(ordering_operators::impl(l, r, rank<1>{}) Oper nullptr) DEFOP(<); DEFOP(>); DEFOP(<=); @@ -191,21 +186,19 @@ struct ordering_operators { #pragma pop_macro("DEFOP") }; -template +template std::false_type is_partially_ordered_with_f(rank<0>); -template -auto is_partially_ordered_with_f(rank<1>, - const T& l = soft_declval(), - const U& r = soft_declval()) // - -> true_t r), - decltype(l < r), - decltype(l >= r), - decltype(l <= r), - decltype(r < l), - decltype(r > l), - decltype(r <= l), - decltype(r >= l)>; +template +auto is_partially_ordered_with_f(rank<1>) + -> true_t() > std::declval()), + decltype(std::declval() < std::declval()), + decltype(std::declval() >= std::declval()), + decltype(std::declval() <= std::declval()), + decltype(std::declval() < std::declval()), + decltype(std::declval() > std::declval()), + decltype(std::declval() <= std::declval()), + decltype(std::declval() >= std::declval())>; template struct is_partially_ordered_with : decltype(is_partially_ordered_with_f(rank<1>{})) {}; diff --git a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/optional.hpp b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/optional.hpp index 3241757ad9..fc1280bc10 100644 --- a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/optional.hpp +++ b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/optional.hpp @@ -86,6 +86,7 @@ using ::std::optional; #include #include #include +#include #include #include #include @@ -99,48 +100,47 @@ namespace v_noabi { namespace stdx { -/** - * @brief Implementation of an std::optional-like class template - * - * Presents mostly the same interface as std::optional from C++17. - * - * @tparam T The type being made "optional" - */ template class optional; -/** - * @brief Exception type thrown upon attempted access to a value-less optional - * via a throwing accessor API. - */ +BSONCXX_PUSH_WARNINGS(); +BSONCXX_DISABLE_WARNING(Clang("-Wweak-vtables")); +// Exception type thrown upon attempted access to a value-less optional via a throwing accessor +// API. class bad_optional_access : public std::exception { public: const char* what() const noexcept override { return "bad_optional_access()"; } }; -/// Tag type to represent an empty optional value +BSONCXX_POP_WARNINGS(); + +// Tag type to represent an empty optional value. struct nullopt_t { explicit constexpr nullopt_t(std::nullptr_t) noexcept {} }; -/// Tag constant to construct or compare with an empty optional value + +// Tag constant to construct or compare with an empty optional value. static constexpr nullopt_t nullopt{nullptr}; -/// Tag used to call the emplacement-constructor of optional + +// Tag used to call the emplacement-constructor of optional. static constexpr struct in_place_t { } in_place; namespace detail { -// Terminates the program when an illegal use of optional is attempted +// Terminates the program when an illegal use of optional is attempted. [[noreturn]] inline void terminate_disengaged_optional(const char* what) noexcept { (void)std::fprintf(stderr, "%s: Invalid attempted use of disengaged optional\n", what); std::terminate(); } -// Throws bad_optional_access for throwing optional member functions + +// Throws bad_optional_access for throwing optional member functions. [[noreturn]] inline void throw_bad_optional() { throw bad_optional_access(); } -// Base class of std::optional. Implementation detail, defined later + +// Base class of std::optional. Implementation detail, defined later. template struct optional_base_class; @@ -152,7 +152,7 @@ std::true_type not_an_optional_f(const T&); template std::false_type not_an_optional_f(const optional&); -// Utility trait to detect specializations of stdx::optional +// Utility trait to detect specializations of stdx::optional. template struct not_an_optional : decltype(not_an_optional_f(std::declval())) {}; @@ -189,36 +189,34 @@ class optional : bsoncxx::detail::equality_operators, bsoncxx::detail::ordering_operators, public detail::optional_base_class::type { public: - /// The type of value held within this optional using value_type = T; - /// An lvalue-reference-to-mutable T using reference = bsoncxx::detail::add_lvalue_reference_t; - /// An lvalue-reference-to-const T using const_reference = bsoncxx::detail::add_lvalue_reference_t>; - /// An rvalue-reference-to-mutable T using rvalue_reference = bsoncxx::detail::add_rvalue_reference_t; - /// An rvalue-reference-to-const T using const_rvalue_reference = bsoncxx::detail::add_rvalue_reference_t>; - /// A pointer-to-mutable T using pointer = bsoncxx::detail::add_pointer_t; - /// A pointer-to-const T using const_pointer = bsoncxx::detail::add_pointer_t; - // Constructors [1] + // Constructors [1]. + optional() = default; constexpr optional(nullopt_t) noexcept {} - // Ctor [2] and [3] are provided by base classes + // Ctor [2] and [3] are provided by base classes. + optional(const optional&) = default; optional(optional&&) = default; + // Same with assignments + optional& operator=(const optional&) = default; optional& operator=(optional&&) = default; ~optional() = default; // In-place constructors + template bsoncxx_cxx14_constexpr explicit optional(in_place_t, Args&&... args) noexcept( noexcept(T(BSONCXX_FWD(args)...))) { @@ -306,7 +304,8 @@ class optional : bsoncxx::detail::equality_operators, return this->has_value(); } - // Unchecked dereference operators + // Unchecked dereference operators. + bsoncxx_cxx14_constexpr reference operator*() & noexcept { _assert_has_value("operator*() &"); return this->_storage.value; @@ -324,7 +323,8 @@ class optional : bsoncxx::detail::equality_operators, return static_cast(**this); } - // (Unchecked) member-access operators + // (Unchecked) member-access operators. + bsoncxx_cxx14_constexpr pointer operator->() noexcept { _assert_has_value("operator->()"); return std::addressof(**this); @@ -334,7 +334,8 @@ class optional : bsoncxx::detail::equality_operators, return std::addressof(**this); } - // Checked accessors + // Checked accessors. + bsoncxx_cxx14_constexpr reference value() & { _throw_if_empty(); return **this; @@ -352,7 +353,8 @@ class optional : bsoncxx::detail::equality_operators, return static_cast(**this); } - // Checked value-or-alternative + // Checked value-or-alternative. + template bsoncxx_cxx14_constexpr value_type value_or(U&& dflt) const& { if (has_value()) { @@ -385,35 +387,27 @@ class optional : bsoncxx::detail::equality_operators, } }; -/** - * @brief Construct an optional by decay-copying the given value into a new - * optional> - * - * @param value The value being made into an optional - */ +// Construct an optional by decay-copying the given value into a new optional>. +// +// @param value The value being made into an optional. template bsoncxx_cxx14_constexpr optional> make_optional(T&& value) noexcept( std::is_nothrow_constructible, T&&>::value) { return optional>(BSONCXX_FWD(value)); } -/** - * @brief Emplace-construct a new optional of the given type with the given - * constructor arguments - * - * @tparam T The type to be constructed - * @param args Constructor arguments - */ +// Emplace-construct a new optional of the given type with the given constructor arguments. +// +// @tparam T The type to be constructed +// @param args Constructor arguments template bsoncxx_cxx14_constexpr optional make_optional(Args&&... args) noexcept( std::is_nothrow_constructible::value) { return optional(in_place, BSONCXX_FWD(args)...); } -/** - * @brief Emplace-construct a new optional of the given type with the given - * arguments (accepts an init-list as the first argument) - */ +// Emplace-construct a new optional of the given type with the given arguments (accepts an init-list +// as the first argument). template bsoncxx_cxx14_constexpr optional make_optional(std::initializer_list il, Args&&... args) noexcept( @@ -423,9 +417,7 @@ make_optional(std::initializer_list il, Args&&... args) noexcept( namespace detail { -/** - * @brief Union template that defines the storage for an optional's data. - */ +// Union template that defines the storage for an optional's data. template ::value> union storage_for { // Placeholder member for disengaged optional @@ -452,14 +444,14 @@ union storage_for { storage_for& operator=(const storage_for&) = delete; }; -// Whether a type is copyable, moveable, or immobile +// Whether a type is copyable, moveable, or immobile. enum copymove_classification { copyable, movable, immobile, }; -/// Classify the constructibility of the given type +// Classify the constructibility of the given type. template ::value, bool CanMove = std::is_move_constructible::value> @@ -467,7 +459,7 @@ constexpr copymove_classification classify_construct() { return CanCopy ? copyable : CanMove ? movable : immobile; } -/// Classify the assignability of the given type +// Classify the assignability of the given type. template ::value, bool CanMove = std::is_move_assignable::value> @@ -475,15 +467,17 @@ constexpr copymove_classification classify_assignment() { return CanCopy ? copyable : CanMove ? movable : immobile; } -/// Common base class for optional storage implementation +// Common base class for optional storage implementation +// +// @tparam T template class optional_common_base; -/// Define the special member constructors for optional +// Define the special member constructors for optional. template ()> struct optional_construct_base; -/// Define the special member assignment operators for optional +// Define the special member assignment operators for optional. template ()> struct optional_assign_base; @@ -499,15 +493,19 @@ struct optional_assign_base : optional_construct_base {}; template struct optional_assign_base : optional_construct_base { - // Constructors defer to base + // Constructors defer to base. + optional_assign_base() = default; optional_assign_base(optional_assign_base const&) = default; optional_assign_base(optional_assign_base&&) = default; ~optional_assign_base() = default; - // No copy + // Disallow copies. + bsoncxx_cxx14_constexpr optional_assign_base& operator=(const optional_assign_base&) = delete; - // Allow move-assign: + + // Allow move-assignment. + bsoncxx_cxx14_constexpr optional_assign_base& operator=(optional_assign_base&& other) = default; }; @@ -548,12 +546,14 @@ template <> struct optional_destruct_helper { template struct base : optional_common_base { - // Special members defer to base + // Special members defer to base. + base() = default; base(base const&) = default; base(base&&) = default; base& operator=(const base&) = default; base& operator=(base&&) = default; + ~base() { // Here we destroy the contained object during destruction. this->reset(); @@ -563,12 +563,13 @@ struct optional_destruct_helper { template <> struct optional_destruct_helper { - // Just fall-through to the common base, which has no special destructor + // Just fall-through to the common base, which has no special destructor. + template using base = optional_common_base; }; -// Optional's ADL-only operators live here: +// Optional's ADL-only operators are defined here. struct optional_operators_base { template friend bsoncxx_cxx14_constexpr auto tag_invoke(bsoncxx::detail::equal_to, @@ -578,7 +579,11 @@ struct optional_operators_base { if (left.has_value() != right.has_value()) { return false; } + + BSONCXX_PUSH_WARNINGS(); + BSONCXX_DISABLE_WARNING(GNU("-Wfloat-equal")); return !left.has_value() || *left == *right; + BSONCXX_POP_WARNINGS(); } template @@ -586,7 +591,10 @@ struct optional_operators_base { optional const& left, U const& right) noexcept -> bsoncxx::detail:: requires_t, bsoncxx::detail::is_equality_comparable> { + BSONCXX_PUSH_WARNINGS(); + BSONCXX_DISABLE_WARNING(GNU("-Wfloat-equal")); return left.has_value() && *left == right; + BSONCXX_POP_WARNINGS(); } template @@ -606,15 +614,15 @@ struct optional_operators_base { if (right.has_value()) { return compare(*left, *right); } else { - // non-null is greater than any null + // Non-null is greater than any null. return bsoncxx::detail::strong_ordering::greater; } } else { if (right.has_value()) { - // Null is less than any non-null + // Null is less than any non-null. return bsoncxx::detail::strong_ordering::less; } else { - // Both are null + // Both are null. return bsoncxx::detail::strong_ordering::equal; } } @@ -630,7 +638,7 @@ struct optional_operators_base { if (left.has_value()) { return compare(*left, right); } - // null optional is less-than any non-null value + // Null optional is less-than any non-null value. return bsoncxx::detail::strong_ordering::less; } @@ -654,7 +662,7 @@ struct optional_swap_mixin { } }; -// Common base class of all optionals +// Common base class of all optionals. template class optional_common_base : optional_operators_base, optional_swap_mixin { using storage_type = detail::storage_for>; @@ -689,10 +697,7 @@ class optional_common_base : optional_operators_base, optional_swap_mixin { return *this; } - /** - * @internal - * @brief If the optional is holding a value, destroy that value and set ourselves null - */ + // If the optional is holding a value, destroy that value and set ourselves null. void reset() noexcept { if (this->_has_value) { this->_storage.value.~T(); @@ -700,11 +705,8 @@ class optional_common_base : optional_operators_base, optional_swap_mixin { this->_has_value = false; } - /** - * @internal - * @brief If the optional is holding a value, destroy that value. Construct - * a new value in-place using the given arguments. - */ + // If the optional is holding a value, destroy that value. Construct a new value in-place using + // the given arguments. template T& emplace(Args&&... args) { this->reset(); @@ -712,11 +714,8 @@ class optional_common_base : optional_operators_base, optional_swap_mixin { return this->_storage.value; } - /** - * @internal - * @brief If the optional is holding a value, destroy that value. Construct - * a new value in-place using the given arguments. - */ + // If the optional is holding a value, destroy that value. Construct a new value in-place using + // the given arguments. template T& emplace(std::initializer_list il, Args&&... args) { this->reset(); @@ -724,20 +723,17 @@ class optional_common_base : optional_operators_base, optional_swap_mixin { return this->_storage.value; } - /** - * @internal - * @brief Special swap for optional values that removes need for a temporary - */ + // Special swap for optional values that removes need for a temporary. bsoncxx_cxx14_constexpr void swap(optional_common_base& other) noexcept( std::is_nothrow_move_constructible::value&& bsoncxx::detail::is_nothrow_swappable::value) { if (other._has_value) { if (this->_has_value) { using std::swap; - // Defer to the underlying swap + // Defer to the underlying swap. swap(this->_storage.value, other._storage.value); } else { - // "steal" the other's value + // "steal" the other's value. this->emplace(std::move(other._storage.value)); other.reset(); } @@ -745,7 +741,7 @@ class optional_common_base : optional_operators_base, optional_swap_mixin { other.emplace(std::move(this->_storage.value)); this->reset(); } else { - // Neither optional has a value, so do nothing + // Neither optional has a value, so do nothing. } } @@ -754,11 +750,8 @@ class optional_common_base : optional_operators_base, optional_swap_mixin { storage_type _storage; bool _has_value = false; - /** - * @internal - * @brief In-place construct a new value from the given arguments. Assumes - * that the optional does not have a live value. - */ + // In-place construct a new value from the given arguments. Assumes that the optional does not + // have a live value. template void _emplace_construct_anew(Args&&... args) noexcept( std::is_nothrow_constructible::value) { @@ -766,14 +759,11 @@ class optional_common_base : optional_operators_base, optional_swap_mixin { this->_has_value = true; } - /** - * @internal - * @brief Perform the semantics of the assignment operator. - */ + // Perform the semantics of the assignment operator. template void _assign(U&& other_storage) { if (other_storage._has_value) { - // We are receiving a value + // We are receiving a value. if (this->_has_value) { // We already have a value. Invoke the underlying assignment. this->_storage.value = BSONCXX_FWD(other_storage)._storage.value; @@ -782,7 +772,7 @@ class optional_common_base : optional_operators_base, optional_swap_mixin { this->_emplace_construct_anew(BSONCXX_FWD(other_storage)._storage.value); } } else { - // We are receiving nullopt. Destroy our value, if present: + // We are receiving nullopt. Destroy our value, if present. this->reset(); } } @@ -799,7 +789,7 @@ template struct optional_hash { optional_hash() = delete; diff --git a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/string_view.hpp b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/string_view.hpp index 424d07f346..a119bc7d61 100644 --- a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/string_view.hpp +++ b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/string_view.hpp @@ -115,30 +115,22 @@ namespace bsoncxx { namespace v_noabi { namespace stdx { -/** - * @brief Implementation of std::string_view-like class template - */ template > class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail::ordering_operators { public: - // Pointer to (non-const) character type using pointer = Char*; - // Pointer to const-character type using const_pointer = const Char*; - // Type representing the size of a string using size_type = std::size_t; - // Type representing the offset within a string using difference_type = std::ptrdiff_t; - // The type of the string character using value_type = Char; - // Constant sentinel value to represent an impossible/invalid string position + // Constant sentinel value to represent an impossible/invalid string position. static constexpr size_type npos = static_cast(-1); private: - // Pointer to the beginning of the string being viewed + // Pointer to the beginning of the string being viewed. const_pointer _begin = nullptr; - // The size of the array that is being viewed via `_begin` + // The size of the array that is being viewed via `_begin`. size_type _size = 0; public: @@ -150,33 +142,15 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: using const_reverse_iterator = std::reverse_iterator; using reverse_iterator = const_reverse_iterator; - /** - * @brief Default constructor. Constructs to an empty/null string view - */ constexpr basic_string_view() noexcept = default; constexpr basic_string_view(const basic_string_view&) noexcept = default; bsoncxx_cxx14_constexpr basic_string_view& operator=(const basic_string_view&) noexcept = default; - /** - * @brief Construct a new string view from a pointer-to-character and an - * array length. - */ constexpr basic_string_view(const_pointer s, size_type count) : _begin(s), _size(count) {} - /** - * @brief Construct a new string view from a C-style null-terminated character array. - * - * The string size is inferred as-if by strlen() - */ constexpr basic_string_view(const_pointer s) : _begin(s), _size(traits_type::length(s)) {} - /** - * @brief Implicit conversion from string-like ranges. - * - * Requires that `StringLike` is a non-array contiguous range with the same - * value type as this string view, and is a std::string-like value. - */ template constexpr basic_string_view( const std::basic_string& str) noexcept @@ -187,7 +161,6 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: : _begin(sv.data()), _size(sv.size()) {} #endif - // Construction from a null pointer is deleted basic_string_view(std::nullptr_t) = delete; constexpr const_iterator begin() const noexcept { @@ -219,96 +192,59 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: return const_reverse_iterator{crbegin()}; } - /** - * @brief Access the Nth element of the referred-to string - * - * @param offset A zero-based offset within the string to access. Must be less - * than size() - */ constexpr const_reference operator[](size_type offset) const { return _begin[offset]; } - /** - * @brief Access the Nth element of the referred-to string. - * - * @param pos A zero-based offset within the string to access. If not less - * than size(), throws std::out_of_range - */ bsoncxx_cxx14_constexpr const_reference at(size_type pos) const { if (pos >= size()) { throw std::out_of_range{"bsoncxx::stdx::basic_string_view::at()"}; } return _begin[pos]; } - /// Access the first character in the string + constexpr const_reference front() const { return (*this)[0]; } - /// Access the last character in the string + constexpr const_reference back() const { return (*this)[size() - 1]; } - /// Obtain a pointer to the beginning of the referred-to character array constexpr const_pointer data() const noexcept { return _begin; } - /// Obtain the length of the referred-to string, in number of characters + constexpr size_type size() const noexcept { return _size; } - /// Obtain the length of the referred-to string, in number of characters + constexpr size_type length() const noexcept { return size(); } - /// Return `true` if size() == 0, otherwise `false` + constexpr bool empty() const noexcept { return size() == 0; } - /// Return the maximum value that could be returned by size() + constexpr size_type max_size() const noexcept { return static_cast(std::numeric_limits::max()); } - /** - * @brief In-place modify the string_view to view N fewer characters from the beginning - * - * @param n The number of characters to remove from the beginning. Must be less than size() - */ bsoncxx_cxx14_constexpr void remove_prefix(size_type n) { _begin += n; _size -= n; } - /** - * @brief In-place modify the string_view to view N fewer characters from the end - * - * @param n The number of characters to remove from the end. Must be less than size() - */ bsoncxx_cxx14_constexpr void remove_suffix(size_type n) { _size -= n; } - /** - * @brief Swap the reference with another string_view - */ bsoncxx_cxx14_constexpr void swap(basic_string_view& other) { std::swap(_begin, other._begin); std::swap(_size, other._size); } - /** - * @brief Copy the contents of the viewed string into the given output destination. - * - * @param dest The destination at which to write characters - * @param count The maximum number of characters to copy. - * @param pos The offset within the viewed string to begin copying from. - * @returns The number of characters that were copied to `dest`. The number - * of copied characters is always the lesser of `size()-pos` and `count` - * - * @throws std::out_of_range if pos > size() - */ size_type copy(pointer dest, size_type count, size_type pos = 0) const { if (pos > size()) { throw std::out_of_range{"bsoncxx::stdx::basic_string_view::substr()"}; @@ -318,15 +254,6 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: return count; } - /** - * @brief Obtain a substring of this string - * - * @param pos The zero-based index at which to start the new string. - * @param count The number of characters to include following `pos` in the new string. - * Automatically clamped to the available size - * - * @throws std::out_of_range if `pos` is greater than this->size() - */ bsoncxx_cxx14_constexpr basic_string_view substr(size_type pos = 0, size_type count = npos) const { if (pos > size()) { @@ -335,52 +262,24 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: return basic_string_view(_begin + pos, (std::min)(count, size() - pos)); } - /** - * @brief Compare two strings lexicographically - * - * @param other The "right hand" operand of the comparison - * @returns `0` If *this == other - * @returns `n : n < 0` if *this is "less than" other. - * @returns `n : n > 0` if *this is "greater than" other. - */ constexpr int compare(basic_string_view other) const noexcept { - // Another level of indirection to support restricted C++11 constexpr + // Another level of indirection to support restricted C++11 constexpr. return _compare2(Traits::compare(data(), other.data(), (std::min)(size(), other.size())), other); } - /** - * @brief Compare *this with the given C-string - * - * @returns compare(basic_string_view(cstr)) - */ constexpr int compare(const_pointer cstr) const { return compare(basic_string_view(cstr)); } - /** - * @brief Compare a substring of *this with `other` - * - * @returns substr(po1, count1).compare(other) - */ constexpr int compare(size_type pos1, size_type count1, basic_string_view other) const { return substr(pos1, count1).compare(other); } - /** - * @brief Compare a substring of *this with the given C-string - * - * @returns substr(pos1, count1, basic_string_view(cstr)) - */ constexpr int compare(size_type pos1, size_type count1, const_pointer cstr) const { return compare(pos1, count1, basic_string_view(cstr)); } - /** - * @brief Compare a substring of *this with a substring of `other` - * - * @returns substr(pos1, count1).compare(other.substr(pos2, count2)) - */ constexpr int compare(size_type pos1, size_type count1, basic_string_view other, @@ -389,11 +288,6 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: return substr(pos1, count1).compare(other.substr(pos2, count2)); } - /** - * @brief Compare a substring of *this with a string viewed through the given pointer+size - * - * @returns substr(pos1, count1).compare(basic_string_view(str, count2)) - */ constexpr int compare(size_type pos1, size_type count1, const_pointer str, @@ -401,10 +295,6 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: return substr(pos1, count1).compare(basic_string_view(str, count2)); } - /** - * @brief Find the zero-based offset of the left-most occurrence of the given infix, - * starting with pos. If infix does not occur, returns npos. - */ bsoncxx_cxx14_constexpr size_type find(basic_string_view infix, size_type pos = 0) const noexcept { if (pos > size()) { @@ -412,7 +302,7 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: } basic_string_view sub = this->substr(pos); if (infix.empty()) { - // The empty string is always "present" at the beginning of any string + // The empty string is always "present" at the beginning of any string. return pos; } const_iterator found = std::search(sub.begin(), sub.end(), infix.begin(), infix.end()); @@ -422,13 +312,9 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: return static_cast(found - begin()); } - /** - * @brief Find the zero-based offset of the right-most occurrence of the given infix, - * starting with (and including) pos. If infix does not occur, returns npos. - */ bsoncxx_cxx14_constexpr size_type rfind(basic_string_view infix, size_type pos = npos) const noexcept { - // Calc the endpos where searching should begin, which includes the infix size + // Calc the endpos where searching should begin, which includes the infix size. const size_type substr_size = pos != npos ? pos + infix.size() : pos; if (infix.empty()) { return (std::min)(pos, size()); @@ -441,34 +327,18 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: return static_cast(rend() - f) - infix.size(); } - /** - * @brief Find the zero-based index of the left-most occurrence of any character of the given - * set, starting at pos - */ constexpr size_type find_first_of(basic_string_view set, size_type pos = 0) const noexcept { return _find_if(pos, [&](value_type chr) { return set.find(chr) != npos; }); } - /** - * @brief Find the zero-based index of the right-most occurrence of any character of the - * given set, starting at (and including) pos - */ constexpr size_type find_last_of(basic_string_view set, size_type pos = npos) const noexcept { return _rfind_if(pos, [&](value_type chr) { return set.find(chr) != npos; }); } - /** - * @brief Find the zero-based index of the left-most occurrence of any character that - * is NOT a member of the given set of characters - */ constexpr size_type find_first_not_of(basic_string_view set, size_type pos = 0) const noexcept { return _find_if(pos, [&](value_type chr) { return set.find(chr) == npos; }); } - /** - * @brief Find the zero-based index of the right-most occurrence of any character that - * is NOT a member of the given set of characters, starting at (and including) pos - */ constexpr size_type find_last_not_of(basic_string_view set, size_type pos = npos) const noexcept { return _rfind_if(pos, [&](value_type chr) { return set.find(chr) == npos; }); @@ -487,6 +357,7 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: return Name(basic_string_view(cstr), pos); \ } \ BSONCXX_FORCE_SEMICOLON + DECL_FINDERS(find, 0); DECL_FINDERS(rfind, npos); DECL_FINDERS(find_first_of, 0); @@ -495,9 +366,7 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: DECL_FINDERS(find_last_not_of, npos); #pragma pop_macro("DECL_FINDERS") - /** - * @brief Explicit-conversion to a std::basic_string - */ + // Explicit-conversion to a std::basic_string. template explicit operator std::basic_string() const { return std::basic_string(data(), size()); @@ -510,20 +379,20 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: #endif private: - // Additional level-of-indirection for constexpr compare() + // Additional level-of-indirection for constexpr compare(). constexpr int _compare2(int diff, basic_string_view other) const noexcept { // "diff" is the diff according to Traits::cmp return diff ? diff : static_cast(size() - other.size()); } - // Implementation of equality comparison + // Implementation of equality comparison. constexpr friend bool tag_invoke(bsoncxx::detail::equal_to, basic_string_view left, basic_string_view right) noexcept { return left.size() == right.size() && left.compare(right) == 0; } - // Implementation of a three-way-comparison + // Implementation of a three-way-comparison. constexpr friend bsoncxx::detail::strong_ordering tag_invoke( bsoncxx::detail::compare_three_way cmp, basic_string_view left, @@ -538,7 +407,7 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: } // Find the first in-bounds index I in [pos, size()) where the given predicate - // returns true for substr(I). If no index exists, returns npos + // returns true for substr(I). If no index exists, returns npos. template bsoncxx_cxx14_constexpr size_type _find_if(size_type pos, F pred) const noexcept { const auto sub = substr(pos); @@ -566,7 +435,8 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: } }; -// Required to define this here for C++≤14 compatibility. Can be removed in C++≥17 +// Required to define this here for compatibility with C++14 and older. Can be removed in C++17 or +// newer. template const std::size_t basic_string_view::npos; diff --git a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/type_traits.hpp b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/type_traits.hpp index 503a0fdd1b..cbf4e26618 100644 --- a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/type_traits.hpp +++ b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/type_traits.hpp @@ -22,15 +22,11 @@ namespace bsoncxx { namespace detail { -#define bsoncxx_ttparam \ - template \ - class - -/// Obtain the nested ::type of the given type argument +// Obtain the nested ::type of the given type argument template using type_t = typename T::type; -/// Obtain the value_type member type of the given argument +// Obtain the value_type member type of the given argument template using value_type_t = typename T::value_type; @@ -38,6 +34,7 @@ template using enable_if_t = typename std::enable_if::type; #pragma push_macro("DECL_ALIAS") +#undef DECL_ALIAS #define DECL_ALIAS(Name) \ template \ using Name##_t = type_t> @@ -59,63 +56,51 @@ DECL_ALIAS(add_rvalue_reference); template using common_type_t = type_t>; -/** - * @brief Remove top-level const+volatile+reference qualifiers from the given type. - */ +// Remove top-level const+volatile+reference qualifiers from the given type. template using remove_cvref_t = remove_cv_t>; -/** - * @brief Create a reference-to-const for the given type - */ +// Create a reference-to-const for the given type template using const_reference_t = add_lvalue_reference_t>; -// Workaround for CWG issue 1558 +// Workaround for CWG issue 1558. template -struct _just_void_ { +struct just_void { using type = void; }; -/** - * @brief A "do-nothing" alias template that always evaluates to void - * - * @tparam Ts Zero or more type arguments, all discarded - */ + +// A "do-nothing" alias template that always evaluates to void. +// +// @tparam Ts Zero or more type arguments, all discarded template using void_t = #if defined(_MSC_VER) && _MSC_VER < 1910 // Old MSVC requires that the type parameters actually be "used" to trigger SFINAE at caller. - // This was resolved by CWG issue 1558 - typename _just_void_::type; + // This was resolved by CWG issue 1558. + typename just_void::type; #else void; #endif -/** - * @brief Alias for integral_constant - */ +// Alias for integral_constant. template using bool_constant = std::integral_constant; -/** - * @brief Holds a list of types. - * - * This template is never defined, so cannot be used in contexts that require a complete type. - */ +// Holds a list of types. +// +// This template is never defined, so cannot be used in contexts that require a complete type. template struct mp_list; -// Like std::declval, but does not generate a hard error if used. -template -extern add_rvalue_reference_t soft_declval() noexcept; - -/// ## Implementation of the C++11 detection idiom +// Details for implementing the C++11 detection idiom. namespace impl_detection { // Implementation of detection idiom for is_detected: true case template < // A metafunction to try and apply - bsoncxx_ttparam Oper, + template + class Oper, // The arguments to be given. These are deduced from the mp_list argument typename... Args, // Apply the arguments to the metafunction. If this yields a type, this function @@ -126,7 +111,7 @@ std::true_type is_detected_f(mp_list*); // Failure case for is_detected. Because this function takes an elipsis, this is // less preferred than the above overload that accepts a pointer type directly. -template +template