From f573501f44fd8cdc479f1ca830f200c693754ff8 Mon Sep 17 00:00:00 2001 From: Billy Donahue Date: Sat, 13 May 2023 07:47:54 +0000 Subject: SERVER-48898 replace util/concepts.h with real concepts --- src/mongo/bson/bsonobjbuilder.h | 6 +- src/mongo/bson/util/builder.h | 8 +- src/mongo/db/exec/document_value/value.h | 14 +- src/mongo/db/query/optimizer/algebra/operator.h | 18 +- src/mongo/executor/remote_command_request.h | 12 +- src/mongo/platform/mutex.h | 5 +- src/mongo/transport/asio/asio_networking_baton.h | 1 - src/mongo/unittest/assert.h | 23 ++- src/mongo/util/SConscript | 1 - src/mongo/util/concepts.h | 210 ------------------- src/mongo/util/concepts_test.cpp | 170 --------------- src/mongo/util/functional.h | 15 +- src/mongo/util/future.h | 251 ++++++++++++----------- src/mongo/util/future_impl.h | 51 ++--- src/mongo/util/future_test_promise_int.cpp | 1 - src/mongo/util/future_test_utils.h | 1 - src/mongo/util/future_util.h | 26 +-- src/mongo/util/interruptible.h | 5 +- src/mongo/util/invalidating_lru_cache.h | 25 ++- src/mongo/util/lru_cache.h | 28 ++- src/mongo/util/read_through_cache.h | 34 ++- src/mongo/util/registry_list.h | 9 +- 22 files changed, 257 insertions(+), 657 deletions(-) delete mode 100644 src/mongo/util/concepts.h delete mode 100644 src/mongo/util/concepts_test.cpp diff --git a/src/mongo/bson/bsonobjbuilder.h b/src/mongo/bson/bsonobjbuilder.h index be826d5a824..be37f4e9f80 100644 --- a/src/mongo/bson/bsonobjbuilder.h +++ b/src/mongo/bson/bsonobjbuilder.h @@ -539,9 +539,9 @@ public: * Append a map of values as a sub-object. * Note: the keys of the map should be StringData-compatible (i.e. strings). */ - TEMPLATE(typename Map) - REQUIRES(std::is_convertible_v().begin()->first), StringData>) - Derived& append(StringData fieldName, const Map& map) { + template + requires std::is_convertible_v().begin()->first), StringData> + Derived& append(StringData fieldName, const Map& map) { typename std::remove_reference::type bob; for (auto&& [k, v] : map) { bob.append(k, v); diff --git a/src/mongo/bson/util/builder.h b/src/mongo/bson/util/builder.h index 5d7d2d5673c..a3ce39883d7 100644 --- a/src/mongo/bson/util/builder.h +++ b/src/mongo/bson/util/builder.h @@ -53,7 +53,6 @@ #include "mongo/stdx/type_traits.h" #include "mongo/util/allocator.h" #include "mongo/util/assert_util.h" -#include "mongo/util/concepts.h" #include "mongo/util/itoa.h" #include "mongo/util/shared_buffer.h" #include "mongo/util/shared_buffer_fragment.h" @@ -380,8 +379,8 @@ public: appendNumImpl(high); } - REQUIRES_FOR_NON_TEMPLATE(!std::is_same_v) - void appendNum(int64_t j) { + template + requires(!std::is_same_v) void appendNum(int64_t j) { appendNumImpl(j); } @@ -465,7 +464,8 @@ public: * Replaces the buffer backing this BufBuilder with the passed in SharedBuffer. * Only legal to call when this builder is empty and when the SharedBuffer isn't shared. */ - REQUIRES_FOR_NON_TEMPLATE(std::is_same_v) + template + requires std::is_same_v void useSharedBuffer(SharedBuffer buf) { invariant(len() == 0); // Can only do this while empty. invariant(reservedBytes() == 0); diff --git a/src/mongo/db/exec/document_value/value.h b/src/mongo/db/exec/document_value/value.h index c3e3dc78546..1d6cc5fd1a6 100644 --- a/src/mongo/db/exec/document_value/value.h +++ b/src/mongo/db/exec/document_value/value.h @@ -32,7 +32,6 @@ #include "mongo/base/static_assert.h" #include "mongo/base/string_data.h" #include "mongo/db/exec/document_value/value_internal.h" -#include "mongo/util/concepts.h" #include "mongo/util/safe_num.h" #include "mongo/util/uuid.h" @@ -417,22 +416,15 @@ inline void swap(mongo::Value& lhs, mongo::Value& rhs) { lhs.swap(rhs); } -MONGO_MAKE_BOOL_TRAIT(CanConstructValueFrom, - (typename T), - (T), - (T val), - // - Value(std::forward(val))); - /** * This class is identical to Value, but supports implicit creation from any of the types explicitly * supported by Value. */ class ImplicitValue : public Value { public: - TEMPLATE(typename T) - REQUIRES(CanConstructValueFrom) - ImplicitValue(T&& arg) : Value(std::forward(arg)) {} + template + requires std::is_constructible_v ImplicitValue(T&& arg) + : Value(std::forward(arg)) {} ImplicitValue(std::initializer_list values) : Value(convertToValues(values)) {} ImplicitValue(std::vector values) : Value(convertToValues(values)) {} diff --git a/src/mongo/db/query/optimizer/algebra/operator.h b/src/mongo/db/query/optimizer/algebra/operator.h index 1dd75272747..dede8effa6c 100644 --- a/src/mongo/db/query/optimizer/algebra/operator.h +++ b/src/mongo/db/query/optimizer/algebra/operator.h @@ -33,8 +33,6 @@ #include #include -#include "mongo/util/concepts.h" - namespace mongo::optimizer { namespace algebra { @@ -66,19 +64,17 @@ class OpFixedArity : public OpNodeStorage { using Base = OpNodeStorage; public: - TEMPLATE(typename... Ts) - REQUIRES(sizeof...(Ts) == Arity) - OpFixedArity(Ts&&... vals) : Base({std::forward(vals)...}) {} + template + requires(sizeof...(Ts) == Arity) OpFixedArity(Ts&&... vals) + : Base({std::forward(vals)...}) {} - TEMPLATE(int I) - REQUIRES(I >= 0 && I < Arity) - auto& get() noexcept { + template + requires(I >= 0 && I < Arity) auto& get() noexcept { return this->_nodes[I]; } - TEMPLATE(int I) - REQUIRES(I >= 0 && I < Arity) - const auto& get() const noexcept { + template + requires(I >= 0 && I < Arity) const auto& get() const noexcept { return this->_nodes[I]; } }; diff --git a/src/mongo/executor/remote_command_request.h b/src/mongo/executor/remote_command_request.h index 5d8e8fbf8c5..44435615052 100644 --- a/src/mongo/executor/remote_command_request.h +++ b/src/mongo/executor/remote_command_request.h @@ -38,7 +38,6 @@ #include "mongo/executor/hedge_options_util.h" #include "mongo/rpc/metadata.h" #include "mongo/transport/transport_layer.h" -#include "mongo/util/concepts.h" #include "mongo/util/net/hostandport.h" #include "mongo/util/time_support.h" @@ -127,15 +126,16 @@ struct RemoteCommandRequestImpl : RemoteCommandRequestBase { RemoteCommandRequestImpl(); // Allow implicit conversion from RemoteCommandRequest to RemoteCommandRequestOnAny - REQUIRES_FOR_NON_TEMPLATE(std::is_same_v>) - RemoteCommandRequestImpl(const RemoteCommandRequestImpl& other) + template + requires std::is_same_v> RemoteCommandRequestImpl( + const RemoteCommandRequestImpl& other) : RemoteCommandRequestBase(other), target({other.target}) {} // Allow conversion from RemoteCommandRequestOnAny to RemoteCommandRequest with the index of a // particular host - REQUIRES_FOR_NON_TEMPLATE(std::is_same_v) - RemoteCommandRequestImpl(const RemoteCommandRequestImpl>& other, - size_t idx) + template + requires std::is_same_v RemoteCommandRequestImpl( + const RemoteCommandRequestImpl>& other, size_t idx) : RemoteCommandRequestBase(other), target(other.target[idx]) {} RemoteCommandRequestImpl(RequestId requestId, diff --git a/src/mongo/platform/mutex.h b/src/mongo/platform/mutex.h index 94361dd938e..a7f19d773d6 100644 --- a/src/mongo/platform/mutex.h +++ b/src/mongo/platform/mutex.h @@ -41,7 +41,6 @@ #include "mongo/platform/source_location.h" #include "mongo/stdx/mutex.h" #include "mongo/util/assert_util.h" -#include "mongo/util/concepts.h" #include "mongo/util/decorable.h" #include "mongo/util/duration.h" #include "mongo/util/hierarchical_acquisition.h" @@ -196,8 +195,8 @@ inline auto& getDiagnosticListenerState() noexcept { * DiagnosticListeners subclass, please provide the switch on that subclass to noop its * functions. It is only safe to add a DiagnosticListener during a MONGO_INITIALIZER. */ -TEMPLATE(typename ListenerT) -REQUIRES(std::is_base_of_v) +template +requires std::is_base_of_v void installDiagnosticListener() { auto& state = getDiagnosticListenerState(); diff --git a/src/mongo/transport/asio/asio_networking_baton.h b/src/mongo/transport/asio/asio_networking_baton.h index 122962fc54f..3d3086a30b1 100644 --- a/src/mongo/transport/asio/asio_networking_baton.h +++ b/src/mongo/transport/asio/asio_networking_baton.h @@ -40,7 +40,6 @@ #include "mongo/stdx/unordered_map.h" #include "mongo/transport/asio/asio_session.h" #include "mongo/transport/baton.h" -#include "mongo/util/concepts.h" #include "mongo/util/functional.h" #include "mongo/util/future.h" #include "mongo/util/hierarchical_acquisition.h" diff --git a/src/mongo/unittest/assert.h b/src/mongo/unittest/assert.h index 62e71077982..7d94d57c709 100644 --- a/src/mongo/unittest/assert.h +++ b/src/mongo/unittest/assert.h @@ -441,7 +441,6 @@ public: StringData a, StringData b); - // Use a single implementation (identical to the templated one) for all pointer and array types. // Note: this is selected instead of the StringData overload for char* and string literals // because they are supposed to compare pointers, not contents. @@ -451,16 +450,18 @@ public: StringData bExpression, const void* a, const void* b); - TEMPLATE(typename A, typename B) - REQUIRES(!(std::is_convertible_v && std::is_convertible_v)&& // - !(std::is_pointer_v && std::is_pointer_v)&& // - !(std::is_array_v && std::is_array_v)) - static ComparisonAssertion make(const char* theFile, - unsigned theLine, - StringData aExpression, - StringData bExpression, - const A& a, - const B& b) { + + template + requires( // + !(std::is_convertible_v && std::is_convertible_v)&& // + !(std::is_pointer_v && std::is_pointer_v)&& // + !(std::is_array_v && std::is_array_v)) // + static ComparisonAssertion make(const char* theFile, + unsigned theLine, + StringData aExpression, + StringData bExpression, + const A& a, + const B& b) { return ComparisonAssertion(theFile, theLine, aExpression, bExpression, a, b); } diff --git a/src/mongo/util/SConscript b/src/mongo/util/SConscript index aff0ed44fef..992990e9fbc 100644 --- a/src/mongo/util/SConscript +++ b/src/mongo/util/SConscript @@ -748,7 +748,6 @@ icuEnv.CppUnitTest( 'base64_test.cpp', 'cancellation_test.cpp', 'clock_source_mock_test.cpp', - 'concepts_test.cpp', 'container_size_helper_test.cpp', 'ctype_test.cpp', 'decimal_counter_test.cpp', diff --git a/src/mongo/util/concepts.h b/src/mongo/util/concepts.h deleted file mode 100644 index fcee167037d..00000000000 --- a/src/mongo/util/concepts.h +++ /dev/null @@ -1,210 +0,0 @@ -/** - * Copyright (C) 2018-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * 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 - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * . - * - * 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 Server Side 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 - -#if defined(__cpp_concepts) - -// -// These macros provide an emulation of C++20-style requires-clauses and requires-expression. These -// are part of the "Concepts" feature, however this does not provide a way to emulate the definition -// of actual concepts. You will need to continue either using the std type_traits, or define your -// own constexpr bools. -// -// The emulation does allow overloading based on requirements, however because it doesn't have a way -// to define actual concepts, there is no subsumption/refinement rules. In other words, you are -// responsible for ensuring that only one overload (with the same arguments) will match a given -// call, the compiler won't select the best one. eg, with real concepts support, you can overload -// these functions and it will do the right thing: -// template void doThing(T); -// template requires(IsFoo) void doThing(T); -// template requires(IsFoo && IsBar) void doThing(T); -// -// With the emulation, you need to explicitly make them all mutually exclusive: -// template requires(!IsFoo) void doThing(T); -// template requires( IsFoo && !IsBar) void doThing(T); -// template requires( IsFoo && IsBar) void doThing(T); -// - -/** - * Use "TEMPLATE(typename T)" instead of "template " when you are using the REQUIRES - * macros. - */ -#define TEMPLATE(...) template <__VA_ARGS__> - -/** - * Disables this template if the argument evaluates to false at compile time. - * - * Use the OUT_OF_LINE_DEF version when you are defining the template out of line following an - * earlier forward declaration. - * - * Must be placed between the TEMPLATE() macro and the declaration (ie it doesn't support the - * "trailing requires clause" style). Can not be used to enable/disable explicit specializations, - * they will need to match exactly one version of the primary template. - * - * Be careful will top-level commas, because everything before the comma will be ignored. - * - * Example (you could also just define the body with the initial declaration): - * - * TEMPLATE(typename Callback) - * REQUIRES(std::is_invocable_v) - * void registerCallback(Callback&& cb); - * - * TEMPLATE(typename Callback) - * REQUIRES_OUT_OF_LINE_DEF(std::is_invocable_v) - * void registerCallback(Callback&& cb) { stuff } - */ -#define REQUIRES(...) requires(__VA_ARGS__) -#define REQUIRES_OUT_OF_LINE_DEF(...) requires(__VA_ARGS__) - -/** - * Use this on a non-template to impose requirements on it. With *very* few exceptions, this should - * only be used on non-template methods inside of a class template. - * - * Due to limitations of the emulation, you cannot forward declare methods this is used with. - * - * Example: - * template - * struct Holder { - * REQUIRES_FOR_NON_TEMPLATE(sizeof(T) == 4) - * void doThing() {} - * - * REQUIRES_FOR_NON_TEMPLATE(sizeof(T) == 8) - * void doThing() {} - * }; - */ -#define REQUIRES_FOR_NON_TEMPLATE(...) \ - template \ - requires(__VA_ARGS__) - -/** - * Defines a boolean trait that is true if a set of expressions compiles. - * - * Args (some are lists that must be wrapped in parens): - * name - name of the template - * (tpl_params) - template parameters for the trait definition (ie with typename) - * (tpl_args) - template arguments for a usage of the trait (ie without typename) - * (decls) - declarations of variables used in the trait's expression - * exprs - the expressions that are tested to see if they compile - * - * Examples (the // separator tends to improve readability with clang-format): - * MONGO_MAKE_BOOL_TRAIT(isAddable, - * (typename LHS, typename RHS), - * (LHS, RHS), - * (LHS& mutableLhs, const LHS& lhs, const RHS& rhs), - * // - * mutableLhs += rhs); - * lhs + rhs, - * - * MONGO_MAKE_BOOL_TRAIT(isCallable, - * (typename Func, typename... Args), - * (Func, Args...), - * (Func& func, Args&&... args), - * // - * func(args...)); - * - * WARNING: This only works for compiler failures in the "immediate context" of the expression. - * For example, if a function is templated to take all arguments, but the body will fail to - * compile with some, isCallable will either return true or cause a hard compile error. - * These should only be used with well-constrained functions. - * - * We need to use a real concept to work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90287. - * Still using a constexpr bool in the public API for consistency with the no-concepts - * implementation so it doesn't behave like a concept during normalization and overload resolution. - */ -#define MONGO_MAKE_BOOL_TRAIT(name, tpl_params, tpl_args, decls, /*exprs*/...) \ - template \ - MONGO_MAKE_BOOL_TRAIT_CONCEPTS_KEYWORD make_trait_impl_##name##_concept = \ - requires(MONGO_MAKE_BOOL_TRAIT_HELPER_EXPAND decls) { \ - {__VA_ARGS__}; \ - }; \ - template \ - constexpr inline bool name = \ - make_trait_impl_##name##_concept - -// Everything under here is an implementation detail, so you should only need to read it if you are -// looking to change or add something. The whole public API is described above. - -#if __cpp_concepts <= 201507 // gcc-8 still uses concepts TS syntax. -#define MONGO_MAKE_BOOL_TRAIT_CONCEPTS_KEYWORD concept bool -#else -#define MONGO_MAKE_BOOL_TRAIT_CONCEPTS_KEYWORD concept -#endif - -#else -// This is the polyfill for when not using concepts-enabled compilers. - -#define TEMPLATE(...) template <__VA_ARGS__, // intentionally left open; closed below. - -// Note: the best error messages are generated when __VA_ARGS__ is the direct first argument of -// enable_if_t, or directly inside of the parens of a decltype without an extra set of parens. -// If you want to alter these, be sure to check error messages on clang and gcc! -#define REQUIRES(...) std::enable_if_t<(__VA_ARGS__), int> = 0 > - -// Same as above, but without the default argument since some compilers (correctly) disallow -// repeating the default argument on the definition. -#define REQUIRES_OUT_OF_LINE_DEF(...) std::enable_if_t<(__VA_ARGS__), int> > - -// Need the second arg in the template to depend on both a template argument (so it is dependent), -// and the current line number (so it can be overloaded). The __VA_ARGS__ expression will generally -// be a constant expression at parse time (or class instantiation time), so in order to allow more -// than one overload that is false, we need to defer the evaluation of the outer enable_if_t to -// function instantiation time. -#define REQUIRES_FOR_NON_TEMPLATE(...) \ - template > = 0> - -// Works by declaring a function template taking `decls` arguments and using expression-SFINAE using -// `exprs` on the return type. A bool is defined as true if it is possible to instantiate the -// template with the supplied arguments by taking its address. -#define MONGO_MAKE_BOOL_TRAIT(name, tpl_params, tpl_args, decls, /*exprs*/...) \ - template \ - auto make_trait_impl_##name##_fn(MONGO_MAKE_BOOL_TRAIT_HELPER_EXPAND decls) \ - ->decltype(__VA_ARGS__); \ - \ - template \ - constexpr inline bool make_trait_impl_##name##_bool = false; \ - \ - template \ - constexpr inline bool make_trait_impl_##name##_bool< \ - std::void_t< \ - decltype(&make_trait_impl_##name##_fn)>, \ - MONGO_MAKE_BOOL_TRAIT_HELPER_EXPAND tpl_args> = true; \ - \ - template \ - constexpr inline bool name = \ - make_trait_impl_##name##_bool - -#endif - -// Strips off wrapping parens used to group some arguments. Use *without* any parens. -#define MONGO_MAKE_BOOL_TRAIT_HELPER_EXPAND(...) __VA_ARGS__ diff --git a/src/mongo/util/concepts_test.cpp b/src/mongo/util/concepts_test.cpp deleted file mode 100644 index bf9efa260f8..00000000000 --- a/src/mongo/util/concepts_test.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/** - * Copyright (C) 2019-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * 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 - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * . - * - * 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 Server Side 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 "mongo/platform/basic.h" - -#include "mongo/util/concepts.h" - -#include -#include -#include - -#include "mongo/unittest/unittest.h" - -namespace mongo { -namespace { - -// Everything this test tests is tests at compile time. If it compiles, it is a success. -// Intentionally using different metaprogramming techniques as in concepts.h to ensure that the test -// doesn't false negative due to the same compiler bug that would cause problems in the real -// implementation. - -template -using Overload = std::integral_constant; - -// Using overload resolution in test to ensure a useful error message. -#define ASSERT_SELECTS_OVERLOAD(num, ...) \ - int compileTestName(Overload); \ - static_assert(sizeof(decltype(compileTestName(__VA_ARGS__)))); - -// Actual tests are below here. Note to anyone thinking of adding more, You should always have at -// least three overloads with the same signature, since some bugs would only be visible if multiple -// overloads would be disabled. - -template -struct NonTemplateTest { - REQUIRES_FOR_NON_TEMPLATE(sizeof(T) == 4) - static void test() {} - - REQUIRES_FOR_NON_TEMPLATE(sizeof(T) == 8) - static void test() {} - - REQUIRES_FOR_NON_TEMPLATE(sizeof(T) == 9) - static void test() {} -}; - -template -constexpr inline auto sizeof_ = sizeof(T); - -static_assert(std::is_void_v::test())>); -static_assert(std::is_void_v::test())>); -ASSERT_DOES_NOT_COMPILE(CharNonTemplateTest, typename Char = char, NonTemplateTest::test()); - -// Uncomment to see error message. -// auto x = NonTemplateTest::test(); - -TEMPLATE(typename T) -REQUIRES(sizeof(T) == 0) -Overload<1> requiresTest() { - return {}; -} - -TEMPLATE(typename T) -REQUIRES(sizeof(T) == 1) -Overload<2> requiresTest() { - return {}; -} - -TEMPLATE(typename T) -REQUIRES(sizeof(T) == 4) -Overload<3> requiresTest() { - return {}; -} - -// Note: it is valid to overload template args with typename vs NTTP. -TEMPLATE(int I) -REQUIRES(I == 0) -Overload<11> requiresTest() { - return {}; -} - -TEMPLATE(int I) -REQUIRES(I > 0) -Overload<12> requiresTest() { - return {}; -} - -TEMPLATE(int I) -REQUIRES(-10 < I && I < 0) -Overload<13> requiresTest(); - -TEMPLATE(int I) -REQUIRES_OUT_OF_LINE_DEF(-10 < I && I < 0) -Overload<13> requiresTest() { - return {}; -} - -ASSERT_SELECTS_OVERLOAD(2, requiresTest()); -ASSERT_SELECTS_OVERLOAD(3, requiresTest()); -ASSERT_DOES_NOT_COMPILE(Int64RequiresTest, typename Int64_t = int64_t, requiresTest()); - -ASSERT_SELECTS_OVERLOAD(11, requiresTest<0>()); -ASSERT_SELECTS_OVERLOAD(12, requiresTest<1>()); -ASSERT_SELECTS_OVERLOAD(13, requiresTest<-1>()); -ASSERT_DOES_NOT_COMPILE(IntRequiresTest, int i = -10, requiresTest()); - -MONGO_MAKE_BOOL_TRAIT(isAddable, - (typename LHS, typename RHS), - (LHS, RHS), - (LHS & mutableLhs, const LHS& lhs, const RHS& rhs), - // - mutableLhs += rhs, - lhs + rhs); - -static_assert(isAddable); -static_assert(isAddable); -static_assert(isAddable); -static_assert(!isAddable); -static_assert(!isAddable); - - -MONGO_MAKE_BOOL_TRAIT(isCallable, - (typename Func, typename... Args), - (Func, Args...), - (Func & func, Args&&... args), - // - func(args...)); - -static_assert(isCallable); -static_assert(!isCallable); -static_assert(isCallable); -static_assert(isCallable); -static_assert(isCallable); -static_assert(isCallable); -static_assert(isCallable); -static_assert(isCallable); -static_assert(!isCallable); -static_assert(!isCallable); -static_assert(!isCallable); - -// The unittest framework gets angry if you have no tests. -TEST(Concepts, DummyTest) {} - -} // namespace -} // namespace mongo diff --git a/src/mongo/util/functional.h b/src/mongo/util/functional.h index c697d267aaa..8d53fbfb5de 100644 --- a/src/mongo/util/functional.h +++ b/src/mongo/util/functional.h @@ -34,7 +34,6 @@ #include "mongo/stdx/type_traits.h" #include "mongo/util/assert_util.h" -#include "mongo/util/concepts.h" namespace mongo { template @@ -61,10 +60,11 @@ class function_ref; template class function_ref { public: - TEMPLATE(typename F) - REQUIRES(std::is_invocable_r_v && - !std::is_same_v, function_ref>) - /*implicit*/ function_ref(F&& f) noexcept { + /** Implicitly convertible from any `f` callable with signature `RetType f(Args...)`. */ + template + requires(std::is_invocable_r_v && + !std::is_same_v, function_ref>) function_ref(F&& f) + noexcept { // removing then re-adding pointer ensures that (language-level) function references and // function pointer are treated the same. using Pointer = std::add_pointer_t>>; @@ -114,9 +114,8 @@ public: * somebody really needs it, we could try to allow T& but not T&&, since T& is less likely to * dangle, but I don't think there is an actual use case for this, so not doing it at this time. */ - TEMPLATE(typename T) - REQUIRES(!std::is_function_v>) - function_ref& operator=(T) = delete; + template + requires(!std::is_function_v>) function_ref& operator=(T) = delete; RetType operator()(Args... args) const { return _adapter(_target, std::forward(args)...); diff --git a/src/mongo/util/future.h b/src/mongo/util/future.h index 63eddbcbff0..986da3f7fa7 100644 --- a/src/mongo/util/future.h +++ b/src/mongo/util/future.h @@ -143,7 +143,8 @@ public: return SemiFuture(Impl::makeReady(std::move(val))); } - REQUIRES_FOR_NON_TEMPLATE(std::is_void_v) + template + requires std::is_void_v static SemiFuture makeReady() { return SemiFuture(Impl::makeReady()); } @@ -296,9 +297,9 @@ private: }; // Deduction Guides -TEMPLATE(typename T) -REQUIRES(!isStatusOrStatusWith && !future_details::isFutureLike) -SemiFuture(T)->SemiFuture; +template +requires(!isStatusOrStatusWith && !future_details::isFutureLike) SemiFuture(T) +->SemiFuture; template SemiFuture(StatusWith) -> SemiFuture; @@ -343,7 +344,8 @@ public: static Future makeReady(StatusWith val) { return Future(Impl::makeReady(std::move(val))); } - REQUIRES_FOR_NON_TEMPLATE(std::is_void_v) + template + requires std::is_void_v static Future makeReady() { return Future(Impl::makeReady()); } @@ -366,10 +368,9 @@ public: * * TODO decide how to handle func throwing. */ - TEMPLATE(typename Policy, typename Func) - REQUIRES(future_details::isCallableExactR>&& - isFuturePolicy) - void getAsync(Policy policy, Func&& func) && noexcept { + template + requires(future_details::isCallableExactR>&& + isFuturePolicy) void getAsync(Policy policy, Func&& func) && noexcept { std::move(this->_impl).getAsync(policy, std::forward(func)); } @@ -408,9 +409,9 @@ public: * The callback takes a T and can return anything (see above for how Statusy and Futurey returns * are handled.) */ - TEMPLATE(typename Policy, typename Func) - REQUIRES(future_details::isCallable&& isFuturePolicy) - /*see above*/ auto then(Policy policy, Func&& func) && noexcept { + template + requires(future_details::isCallable&& isFuturePolicy) auto then( + Policy policy, Func&& func) && noexcept { return wrap(std::move(this->_impl).then(policy, std::forward(func))); } @@ -421,9 +422,9 @@ public: * The callback takes a StatusOrStatusWith and can return anything (see above for how Statusy * and Futurey returns are handled.) */ - TEMPLATE(typename Policy, typename Func) - REQUIRES(future_details::isCallable>&& isFuturePolicy) - /*see above*/ auto onCompletion(Policy policy, Func&& func) && noexcept { + template + requires(future_details::isCallable>&& + isFuturePolicy) auto onCompletion(Policy policy, Func&& func) && noexcept { return wrap( std::move(this->_impl).onCompletion(policy, std::forward(func))); } @@ -441,9 +442,9 @@ public: * The callback takes a non-OK Status and returns a possibly-wrapped T (see above for how * Statusy and Futurey returns are handled.) */ - TEMPLATE(typename Policy, typename Func) - REQUIRES(future_details::isCallableR&& isFuturePolicy) - /*see above*/ auto onError(Policy policy, Func&& func) && noexcept { + template + requires(future_details::isCallableR&& isFuturePolicy) auto onError( + Policy policy, Func&& func) && noexcept { return wrap(std::move(this->_impl).onError(policy, std::forward(func))); } @@ -454,9 +455,9 @@ public: * The callback takes a non-OK Status and returns a possibly-wrapped T (see above for how * Statusy and Futurey returns are handled.) */ - TEMPLATE(ErrorCodes::Error code, typename Policy, typename Func) - REQUIRES(future_details::isCallableR&& isFuturePolicy) - /*see above*/ auto onError(Policy policy, Func&& func) && noexcept { + template + requires(future_details::isCallableR&& isFuturePolicy) auto onError( + Policy policy, Func&& func) && noexcept { return wrap( std::move(this->_impl).template onError(policy, std::forward(func))); } @@ -468,9 +469,10 @@ public: * The callback takes a non-OK Status and returns a possibly-wrapped T (see above for how * Statusy and Futurey returns are handled.) */ - TEMPLATE(ErrorCategory category, typename Policy, typename Func) - REQUIRES(future_details::isCallableR&& isFuturePolicy) - /*see above*/ auto onErrorCategory(Policy policy, Func&& func) && noexcept { + template + requires(future_details::isCallableR&& + isFuturePolicy) auto onErrorCategory(Policy policy, + Func&& func) && noexcept { return wrap( std::move(this->_impl) .template onErrorCategory(policy, std::forward(func))); @@ -496,9 +498,9 @@ public: * * The callback takes a const T& and must return void. */ - TEMPLATE(typename Policy, typename Func) - REQUIRES(future_details::isCallableExactR&& isFuturePolicy) - Future tap(Policy policy, Func&& func) && noexcept { + template + requires(future_details::isCallableExactR&& isFuturePolicy) + Future tap(Policy policy, Func&& func) && noexcept { return Future(std::move(this->_impl).tap(policy, std::forward(func))); } @@ -509,9 +511,9 @@ public: * * The callback takes a non-OK Status and must return void. */ - TEMPLATE(typename Policy, typename Func) - REQUIRES(future_details::isCallableExactR&& isFuturePolicy) - Future tapError(Policy policy, Func&& func) && noexcept { + template + requires(future_details::isCallableExactR&& isFuturePolicy) + Future tapError(Policy policy, Func&& func) && noexcept { return Future(std::move(this->_impl).tapError(policy, std::forward(func))); } @@ -523,10 +525,9 @@ public: * * The callback takes a StatusOrStatusWith and must return void. */ - TEMPLATE(typename Policy, typename Func) - REQUIRES(future_details::isCallableExactR>&& - isFuturePolicy) - Future tapAll(Policy policy, Func&& func) && noexcept { + template + requires(future_details::isCallableExactR>&& + isFuturePolicy) Future tapAll(Policy policy, Func&& func) && noexcept { return Future(std::move(this->_impl).tapAll(policy, std::forward(func))); } @@ -541,50 +542,50 @@ public: * * TODO(SERVER-66126): Remove all tag-taking methods and associated default implementations. */ - TEMPLATE(typename Func) - REQUIRES(future_details::isCallableExactR>) + template + requires future_details::isCallableExactR> void getAsync(Func&& func) && noexcept { std::move(*this).getAsync(destroyDefault, std::forward(func)); } - TEMPLATE(typename Func) - REQUIRES(future_details::isCallable) + template + requires future_details::isCallable auto then(Func&& func) && noexcept { return std::move(*this).then(destroyDefault, std::forward(func)); } - TEMPLATE(typename Func) - REQUIRES(future_details::isCallable>) + template + requires future_details::isCallable> auto onCompletion(Func&& func) && noexcept { return std::move(*this).onCompletion(destroyDefault, std::forward(func)); } - TEMPLATE(typename Func) - REQUIRES(future_details::isCallableR) + template + requires future_details::isCallableR auto onError(Func&& func) && noexcept { return std::move(*this).onError(destroyDefault, std::forward(func)); } - TEMPLATE(ErrorCodes::Error code, typename Func) - REQUIRES(future_details::isCallableR) + template + requires future_details::isCallableR auto onError(Func&& func) && noexcept { return std::move(*this).template onError(destroyDefault, std::forward(func)); } - TEMPLATE(ErrorCategory category, typename Func) - REQUIRES(future_details::isCallableR) + template + requires future_details::isCallableR auto onErrorCategory(Func&& func) && noexcept { return std::move(*this).template onErrorCategory(destroyDefault, std::forward(func)); } - TEMPLATE(typename Func) - REQUIRES(future_details::isCallableExactR) - Future tap(Func&& func) && noexcept { + template + requires future_details::isCallableExactR Future tap( + Func&& func) && noexcept { return std::move(*this).tap(destroyDefault, std::forward(func)); } - TEMPLATE(typename Func) - REQUIRES(future_details::isCallableExactR) - Future tapError(Func&& func) && noexcept { + template + requires future_details::isCallableExactR Future tapError( + Func&& func) && noexcept { return std::move(*this).tapError(destroyDefault, std::forward(func)); } - TEMPLATE(typename Func) - REQUIRES(future_details::isCallableExactR>) - Future tapAll(Func&& func) && noexcept { + template + requires future_details::isCallableExactR> Future + tapAll(Func&& func) && noexcept { return std::move(*this).tapAll(destroyDefault, std::forward(func)); } @@ -607,9 +608,9 @@ private: }; // Deduction Guides -TEMPLATE(typename T) -REQUIRES(!isStatusOrStatusWith && !future_details::isFutureLike) -Future(T)->Future; +template +requires(!isStatusOrStatusWith && !future_details::isFutureLike) Future(T) +->Future; template Future(StatusWith) -> Future; @@ -649,7 +650,8 @@ public: static_assert(!std::is_void_v); } - REQUIRES_FOR_NON_TEMPLATE(std::is_void_v) + template + requires std::is_void_v explicit ExecutorFuture(ExecutorPtr exec) : SemiFuture(), _exec(std::move(exec)) {} /** @@ -690,10 +692,9 @@ public: * Attach a completion callback to asynchronously consume this `ExecutorFuture`'s result. * \see `Future::getAsync()`. */ - TEMPLATE(typename Policy, typename Func) - REQUIRES(future_details::isCallableExactR>&& - isFuturePolicy) - void getAsync(Policy policy, Func&& func) && noexcept { + template + requires(future_details::isCallableExactR>&& + isFuturePolicy) void getAsync(Policy policy, Func&& func) && noexcept { static_assert(std::is_void_v>()))>, "func passed to getAsync must return void"); @@ -713,17 +714,17 @@ public: }); } - TEMPLATE(typename Policy, typename Func) - REQUIRES(future_details::isCallable&& isFuturePolicy) - auto then(Policy policy, Func&& func) && noexcept { + template + requires(future_details::isCallable&& isFuturePolicy) auto then( + Policy policy, Func&& func) && noexcept { return mongo::ExecutorFuture( std::move(_exec), std::move(this->_impl).then(policy, wrapCB(policy, std::forward(func)))); } - TEMPLATE(typename Policy, typename Func) - REQUIRES(future_details::isCallable>&& isFuturePolicy) - auto onCompletion(Policy policy, Func&& func) && noexcept { + template + requires(future_details::isCallable>&& + isFuturePolicy) auto onCompletion(Policy policy, Func&& func) && noexcept { return mongo::ExecutorFuture( std::move(_exec), std::move(this->_impl) @@ -731,27 +732,27 @@ public: wrapCB>(policy, std::forward(func)))); } - TEMPLATE(typename Policy, typename Func) - REQUIRES(future_details::isCallableR&& isFuturePolicy) - ExecutorFuture onError(Policy policy, Func&& func) && noexcept { + template + requires(future_details::isCallableR&& isFuturePolicy) + ExecutorFuture onError(Policy policy, Func&& func) && noexcept { return mongo::ExecutorFuture( std::move(_exec), std::move(this->_impl) .onError(policy, wrapCB(policy, std::forward(func)))); } - TEMPLATE(ErrorCodes::Error code, typename Policy, typename Func) - REQUIRES(future_details::isCallableR&& isFuturePolicy) - ExecutorFuture onError(Policy policy, Func&& func) && noexcept { + template + requires(future_details::isCallableR&& isFuturePolicy) + ExecutorFuture onError(Policy policy, Func&& func) && noexcept { return mongo::ExecutorFuture( std::move(_exec), std::move(this->_impl) .template onError(policy, wrapCB(policy, std::forward(func)))); } - TEMPLATE(ErrorCategory category, typename Policy, typename Func) - REQUIRES(future_details::isCallableR&& isFuturePolicy) - ExecutorFuture onErrorCategory(Policy policy, Func&& func) && noexcept { + template + requires(future_details::isCallableR&& isFuturePolicy) + ExecutorFuture onErrorCategory(Policy policy, Func&& func) && noexcept { return mongo::ExecutorFuture( std::move(_exec), std::move(this->_impl) @@ -773,33 +774,33 @@ public: * * TODO(SERVER-66126): Remove all tag-taking methods and associated default implementations. */ - TEMPLATE(typename Func) - REQUIRES(future_details::isCallableExactR>) + template + requires future_details::isCallableExactR> void getAsync(Func&& func) && noexcept { std::move(*this).getAsync(destroyDefault, std::forward(func)); } - TEMPLATE(typename Func) - REQUIRES(future_details::isCallable) + template + requires future_details::isCallable auto then(Func&& func) && noexcept { return std::move(*this).then(destroyDefault, std::forward(func)); } - TEMPLATE(typename Func) - REQUIRES(future_details::isCallable>) + template + requires future_details::isCallable> auto onCompletion(Func&& func) && noexcept { return std::move(*this).onCompletion(destroyDefault, std::forward(func)); } - TEMPLATE(typename Func) - REQUIRES(future_details::isCallableR) + template + requires future_details::isCallableR auto onError(Func&& func) && noexcept { return std::move(*this).onError(destroyDefault, std::forward(func)); } - TEMPLATE(ErrorCodes::Error code, typename Func) - REQUIRES(future_details::isCallableR) + template + requires future_details::isCallableR auto onError(Func&& func) && noexcept { return std::move(*this).template onError(destroyDefault, std::forward(func)); } - TEMPLATE(ErrorCategory category, typename Func) - REQUIRES(future_details::isCallableR) + template + requires future_details::isCallableR auto onErrorCategory(Func&& func) && noexcept { return std::move(*this).template onErrorCategory(destroyDefault, std::forward(func)); @@ -816,8 +817,8 @@ private: * Future, then schedules a task on _exec to complete the associated promise with the result * of calling func with that argument. */ - TEMPLATE(typename RawArg, typename Policy, typename Func) - REQUIRES(isFuturePolicy) + template + requires isFuturePolicy auto wrapCB(Policy policy, Func&& func) { // Have to take care to never put void in argument position, since that is a hard error. using Result = typename std::conditional_t, @@ -848,9 +849,10 @@ private: }; // Deduction Guides -TEMPLATE(typename T) -REQUIRES(!isStatusOrStatusWith && !future_details::isFutureLike) -ExecutorFuture(ExecutorPtr, T)->ExecutorFuture; +template +requires(!isStatusOrStatusWith && !future_details::isFutureLike) + ExecutorFuture(ExecutorPtr, T) +->ExecutorFuture; template ExecutorFuture(ExecutorPtr, future_details::FutureImpl) -> ExecutorFuture; template @@ -928,13 +930,13 @@ public: * because this method will correctly propagate errors thrown from makeResult(), rather than * ErrorCodes::BrokenPromise. */ - TEMPLATE(typename Policy, typename Func) - REQUIRES(future_details::isCallableR&& isFuturePolicy) - void setWith(Policy policy, Func&& func) noexcept { + template + requires(future_details ::isCallableR&& isFuturePolicy) void setWith( + Policy policy, Func&& func) noexcept { setFrom(Future::makeReady().then(policy, std::forward(func))); } - TEMPLATE(typename Func) - REQUIRES(future_details::isCallableR) + template + requires future_details::isCallableR void setWith(Func&& func) noexcept { setWith(destroyDefault, std::forward(func)); } @@ -962,16 +964,16 @@ public: } // Use emplaceValue(Args&&...) instead. - REQUIRES_FOR_NON_TEMPLATE(!std::is_void_v) - void setFrom(T_unless_void val) noexcept = delete; + template + requires(!std::is_void_v) void setFrom(T_unless_void val) noexcept = delete; // Use setError(Status) instead. - REQUIRES_FOR_NON_TEMPLATE(!std::is_void_v) - void setFrom(Status) noexcept = delete; + template + requires(!std::is_void_v) void setFrom(Status) noexcept = delete; - TEMPLATE(typename... Args) - REQUIRES(std::is_constructible_v || (std::is_void_v && sizeof...(Args) == 0)) - void emplaceValue(Args&&... args) noexcept { + template + requires std::is_constructible_v || + (std::is_void_v && sizeof...(Args) == 0) void emplaceValue(Args&&... args) noexcept { setImpl([&](boost::intrusive_ptr&& sharedState) { sharedState->emplaceValue(std::forward(args)...); }); @@ -1167,9 +1169,9 @@ private: }; // Deduction Guides -TEMPLATE(typename T) -REQUIRES(!isStatusOrStatusWith && !future_details::isFutureLike) -SharedSemiFuture(T)->SharedSemiFuture; +template +requires(!isStatusOrStatusWith && !future_details::isFutureLike) SharedSemiFuture(T) +->SharedSemiFuture; template SharedSemiFuture(StatusWith) -> SharedSemiFuture; @@ -1221,13 +1223,13 @@ public: return SharedSemiFuture(_sharedState); } - TEMPLATE(typename Policy, typename Func) - REQUIRES(future_details::isCallableR&& isFuturePolicy) - void setWith(Policy policy, Func&& func) noexcept { + template + requires(future_details::isCallableR&& isFuturePolicy) void setWith( + Policy policy, Func&& func) noexcept { setFrom(Future::makeReady().then(policy, std::forward(func))); } - TEMPLATE(typename Func) - REQUIRES(future_details::isCallableR) + template + requires future_details::isCallableR void setWith(Func&& func) noexcept { setWith(destroyDefault, std::forward(func)); } @@ -1252,16 +1254,17 @@ public: } // Use emplaceValue(Args&&...) instead. - REQUIRES_FOR_NON_TEMPLATE(!std::is_void_v) - void setFrom(T_unless_void val) noexcept = delete; + template + requires(!std ::is_void_v) void setFrom(T_unless_void val) noexcept = delete; // Use setError(Status) instead. - REQUIRES_FOR_NON_TEMPLATE(!std::is_void_v) - void setFrom(Status) noexcept = delete; + template + requires(!std ::is_void_v) void setFrom(Status) noexcept = delete; - TEMPLATE(typename... Args) - REQUIRES(std::is_constructible_v || (std::is_void_v && sizeof...(Args) == 0)) - void emplaceValue(Args&&... args) noexcept { + template + requires(std::is_constructible_v || + (std::is_void_v && + sizeof...(Args) == 0)) void emplaceValue(Args&&... args) noexcept { invariant(!std::exchange(_haveCompleted, true)); _sharedState->emplaceValue(std::forward(args)...); } @@ -1341,8 +1344,8 @@ auto coerceToFuture(T&& value) { * * Note that if func returns an unready Future, this function will not block until it is ready. */ -TEMPLATE(typename Func) -REQUIRES(future_details::isCallable) +template +requires future_details::isCallable auto makeReadyFutureWith(Func&& func) -> Future> try { if constexpr (std::is_void_v>) { std::forward(func)(); diff --git a/src/mongo/util/future_impl.h b/src/mongo/util/future_impl.h index 940199e975c..1d825db5628 100644 --- a/src/mongo/util/future_impl.h +++ b/src/mongo/util/future_impl.h @@ -641,7 +641,8 @@ struct SharedStateImpl final : SharedStateBase { } } - REQUIRES_FOR_NON_TEMPLATE(std::is_same_v) + template + requires std::is_same_v void setFrom(Status status) { if (status.isOK()) { emplaceValue(); @@ -942,8 +943,8 @@ public: return _shared.getNoThrow(interruptible); } - TEMPLATE(typename Policy, typename Func) - REQUIRES(isFuturePolicy) + template + requires isFuturePolicy void getAsync(Policy policy, Func&& func) && noexcept { static_assert(std::is_void>()))>::value, "func passed to getAsync must return void"); @@ -967,8 +968,8 @@ public: }); } - TEMPLATE(typename Policy, typename Func) - REQUIRES(isFuturePolicy) + template + requires isFuturePolicy auto then(Policy policy, Func&& func) && noexcept { using Result = NormalizedCallResult; if constexpr (!isFutureLike) { @@ -1025,8 +1026,8 @@ public: } } - TEMPLATE(typename Policy, typename Func) - REQUIRES(isFuturePolicy) + template + requires isFuturePolicy auto onCompletion(Policy policy, Func&& func) && noexcept { using Wrapper = StatusOrStatusWith; using Result = NormalizedCallResult>; @@ -1103,9 +1104,9 @@ public: } } - TEMPLATE(typename Policy, typename Func) - REQUIRES(isFuturePolicy) - FutureImpl> onError(Policy policy, Func&& func) && noexcept { + template + requires isFuturePolicy FutureImpl> onError(Policy policy, + Func&& func) && noexcept { using Result = NormalizedCallResult; static_assert( std::is_same>, T>::value, @@ -1160,9 +1161,9 @@ public: } } - TEMPLATE(ErrorCodes::Error code, typename Policy, typename Func) - REQUIRES(isFuturePolicy) - FutureImpl> onError(Policy policy, Func&& func) && noexcept { + template + requires isFuturePolicy FutureImpl> onError(Policy policy, + Func&& func) && noexcept { using Result = NormalizedCallResult; static_assert( std::is_same_v, FakeVoidToVoid>, @@ -1181,9 +1182,9 @@ public: }); } - TEMPLATE(ErrorCategory category, typename Policy, typename Func) - REQUIRES(isFuturePolicy) - FutureImpl> onErrorCategory(Policy policy, Func&& func) && noexcept { + template + requires isFuturePolicy FutureImpl> onErrorCategory( + Policy policy, Func&& func) && noexcept { using Result = NormalizedCallResult; static_assert(std::is_same_v, FakeVoidToVoid>, "func passed to Future::onErrorCategory must return T, StatusWith, " @@ -1200,9 +1201,9 @@ public: }); } - TEMPLATE(typename Policy, typename Func) - REQUIRES(isFuturePolicy) - FutureImpl> tap(Policy policy, Func&& func) && noexcept { + template + requires isFuturePolicy FutureImpl> tap(Policy policy, + Func&& func) && noexcept { static_assert(std::is_void()))>::value, "func passed to tap must return void"); @@ -1212,9 +1213,9 @@ public: [](Func&& failFunc, const Status& status) noexcept {}); } - TEMPLATE(typename Policy, typename Func) - REQUIRES(isFuturePolicy) - FutureImpl> tapError(Policy policy, Func&& func) && noexcept { + template + requires isFuturePolicy FutureImpl> tapError( + Policy policy, Func&& func) && noexcept { static_assert(std::is_void()))>::value, "func passed to tapError must return void"); @@ -1224,9 +1225,9 @@ public: [](Func&& failFunc, const Status& status) noexcept { call(failFunc, status); }); } - TEMPLATE(typename Policy, typename Func) - REQUIRES(isFuturePolicy) - FutureImpl> tapAll(Policy policy, Func&& func) && noexcept { + template + requires isFuturePolicy FutureImpl> tapAll(Policy policy, + Func&& func) && noexcept { static_assert( std::is_void&>()))>::value, "func passed to tapAll must return void"); diff --git a/src/mongo/util/future_test_promise_int.cpp b/src/mongo/util/future_test_promise_int.cpp index 38bc194688c..d710691abfa 100644 --- a/src/mongo/util/future_test_promise_int.cpp +++ b/src/mongo/util/future_test_promise_int.cpp @@ -34,7 +34,6 @@ #include "mongo/stdx/thread.h" #include "mongo/unittest/death_test.h" #include "mongo/unittest/unittest.h" -#include "mongo/util/concepts.h" #include "mongo/util/future_test_utils.h" diff --git a/src/mongo/util/future_test_utils.h b/src/mongo/util/future_test_utils.h index c1695c3e392..6608b254193 100644 --- a/src/mongo/util/future_test_utils.h +++ b/src/mongo/util/future_test_utils.h @@ -34,7 +34,6 @@ #include "mongo/stdx/thread.h" #include "mongo/unittest/death_test.h" #include "mongo/unittest/unittest.h" -#include "mongo/util/concepts.h" #include "mongo/util/executor_test_util.h" #if !defined(__has_feature) diff --git a/src/mongo/util/future_util.h b/src/mongo/util/future_util.h index 5753a3d74e5..eb713f3da39 100644 --- a/src/mongo/util/future_util.h +++ b/src/mongo/util/future_util.h @@ -495,11 +495,11 @@ public: * error as soon as any input future is set with an error. The resulting vector contains the results * of all of the input futures in the same order in which they were provided. */ -TEMPLATE(typename FutureLike, - typename Value = typename FutureLike::value_type, - typename ResultVector = std::vector) -REQUIRES(!std::is_void_v && future_util_details::isFutureOrExecutorFuture) -SemiFuture whenAllSucceed(std::vector&& futures) { +template > +requires(!std::is_void_v && future_util_details::isFutureOrExecutorFuture) + SemiFuture whenAllSucceed(std::vector&& futures) { invariant(futures.size() > 0, future_util_details::kWhenAllSucceedEmptyInputInvariantMsg); // A structure used to share state between the input futures. @@ -559,9 +559,9 @@ SemiFuture whenAllSucceed(std::vector&& futures) { * Variant of whenAllSucceed for void input futures. The only behavior difference is that it returns * SemiFuture instead of SemiFuture>. */ -TEMPLATE(typename FutureLike, typename Value = typename FutureLike::value_type) -REQUIRES(std::is_void_v&& future_util_details::isFutureOrExecutorFuture) -SemiFuture whenAllSucceed(std::vector&& futures) { +template +requires(std::is_void_v&& future_util_details::isFutureOrExecutorFuture) + SemiFuture whenAllSucceed(std::vector&& futures) { invariant(futures.size() > 0, future_util_details::kWhenAllSucceedEmptyInputInvariantMsg); // A structure used to share state between the input futures. @@ -714,11 +714,11 @@ SemiFuture whenAny(std::vector&& futures) { * we peel off the first element of each input list in order to assist the compiler in type * inference and to prevent 0 length lists from compiling. */ -TEMPLATE(typename... FuturePack, - typename FutureLike = std::common_type_t, - typename Value = typename FutureLike::value_type, - typename ResultVector = std::vector) -REQUIRES(future_util_details::isFutureOrExecutorFuture) +template , + typename Value = typename FutureLike::value_type, + typename ResultVector = std::vector> +requires future_util_details::isFutureOrExecutorFuture auto whenAllSucceed(FuturePack&&... futures) { return whenAllSucceed( future_util_details::variadicArgsToVector(std::forward(futures)...)); diff --git a/src/mongo/util/interruptible.h b/src/mongo/util/interruptible.h index 1e9cc070c64..d7ffefcc3f6 100644 --- a/src/mongo/util/interruptible.h +++ b/src/mongo/util/interruptible.h @@ -33,7 +33,6 @@ #include "mongo/platform/mutex.h" #include "mongo/stdx/condition_variable.h" -#include "mongo/util/concepts.h" #include "mongo/util/lockable_adapter.h" #include "mongo/util/scopeguard.h" #include "mongo/util/time_support.h" @@ -255,8 +254,8 @@ public: /** * Get the name for a Latch */ - TEMPLATE(typename LatchT) - REQUIRES(std::is_base_of_v) // + template + requires std::is_base_of_v static StringData getLatchName(const stdx::unique_lock& lk) { return lk.mutex()->getName(); } diff --git a/src/mongo/util/invalidating_lru_cache.h b/src/mongo/util/invalidating_lru_cache.h index 6acde61f6c0..df82059d0f6 100644 --- a/src/mongo/util/invalidating_lru_cache.h +++ b/src/mongo/util/invalidating_lru_cache.h @@ -432,10 +432,9 @@ public: * it could still get evicted if the cache is under pressure. The returned handle must be * destroyed before the owning cache object itself is destroyed. */ - TEMPLATE(typename KeyType) - REQUIRES(IsComparable) - ValueHandle get( - const KeyType& key, + template + requires IsComparable ValueHandle + get(const KeyType& key, CacheCausalConsistency causalConsistency = CacheCausalConsistency::kLatestCached) { stdx::lock_guard lg(_mutex); std::shared_ptr storedValue; @@ -492,8 +491,8 @@ public: * Returns true if the passed 'newTimeInStore' is grater than the time of the currently cached * value or if no value is cached for 'key'. */ - TEMPLATE(typename KeyType) - REQUIRES(IsComparable) + template + requires IsComparable bool advanceTimeInStore(const KeyType& key, const Time& newTimeInStore) { stdx::lock_guard lg(_mutex); std::shared_ptr storedValue; @@ -522,9 +521,9 @@ public: * which can either be from the time of insertion or from the latest call to * 'advanceTimeInStore'. Otherwise, returns a nullptr ValueHandle and Time(). */ - TEMPLATE(typename KeyType) - REQUIRES(IsComparable) - std::pair getCachedValueAndTimeInStore(const KeyType& key) { + template + requires IsComparable std::pair getCachedValueAndTimeInStore( + const KeyType& key) { stdx::lock_guard lg(_mutex); std::shared_ptr storedValue; if (auto it = _cache.find(key); it != _cache.end()) { @@ -548,8 +547,8 @@ public: * Any already returned ValueHandles will start returning isValid = false. Subsequent calls to * 'get' will *not* return value for 'key' until the next call to 'insertOrAssign'. */ - TEMPLATE(typename KeyType) - REQUIRES(IsComparable) + template + requires IsComparable void invalidate(const KeyType& key) { LockGuardWithPostUnlockDestructor guard(_mutex); _invalidate(&guard, key, _cache.find(key)); @@ -641,8 +640,8 @@ private: * the key may not exist, and after this call will no longer be valid and will not be in either * of the maps. */ - TEMPLATE(typename KeyType) - REQUIRES(IsComparable) + template + requires IsComparable void _invalidate(LockGuardWithPostUnlockDestructor* guard, const KeyType& key, typename Cache::iterator it, diff --git a/src/mongo/util/lru_cache.h b/src/mongo/util/lru_cache.h index bdcc5e68a7f..f724e22eea9 100644 --- a/src/mongo/util/lru_cache.h +++ b/src/mongo/util/lru_cache.h @@ -138,9 +138,8 @@ public: /** * Finds an element in the cache by key. */ - TEMPLATE(typename KeyType) - REQUIRES(IsComparable) - iterator find(const KeyType& key) { + template + requires IsComparable iterator find(const KeyType& key) { return promote(key); } @@ -153,9 +152,9 @@ public: * the find(...) method above will prevent the LRUCache from functioning * properly. */ - TEMPLATE(typename KeyType) - REQUIRES(IsComparable) - const_iterator cfind(const KeyType& key) const { + template + requires IsComparable const_iterator cfind(const KeyType& key) + const { auto it = _map.find(key); return (it == _map.end()) ? end() : const_iterator(it->second); } @@ -164,9 +163,8 @@ public: * Promotes the element matching the given key, if one exists in the cache, * to the least recently used element. */ - TEMPLATE(typename KeyType) - REQUIRES(IsComparable) - iterator promote(const KeyType& key) { + template + requires IsComparable iterator promote(const KeyType& key) { auto it = _map.find(key); return (it == _map.end()) ? end() : promote(it->second); } @@ -201,8 +199,8 @@ public: * Removes the element in the cache stored for this key, if one * exists. Returns the count of elements erased. */ - TEMPLATE(typename KeyType) - REQUIRES(IsComparable) + template + requires IsComparable typename Map::size_type erase(const KeyType& key) { auto it = _map.find(key); if (it == _map.end()) { @@ -237,8 +235,8 @@ public: * If the given key has a matching element stored in the cache, returns true. * Otherwise, returns false. */ - TEMPLATE(typename KeyType) - REQUIRES(IsComparable) + template + requires IsComparable bool hasKey(const KeyType& key) const { return _map.find(key) != _map.end(); } @@ -296,8 +294,8 @@ public: return _list.cend(); } - TEMPLATE(typename KeyType) - REQUIRES(IsComparable) + template + requires IsComparable typename Map::size_type count(const KeyType& key) const { return _map.count(key); } diff --git a/src/mongo/util/read_through_cache.h b/src/mongo/util/read_through_cache.h index 3ed61e98e39..d3dcdbfece4 100644 --- a/src/mongo/util/read_through_cache.h +++ b/src/mongo/util/read_through_cache.h @@ -250,11 +250,11 @@ public: * The returned value may be invalid by the time the caller gets to access it, if 'invalidate' * is called for 'key'. */ - TEMPLATE(typename KeyType) - REQUIRES(IsComparable&& std::is_constructible_v) - SharedSemiFuture acquireAsync( - const KeyType& key, - CacheCausalConsistency causalConsistency = CacheCausalConsistency::kLatestCached) { + template + requires(IsComparable&& std::is_constructible_v) + SharedSemiFuture acquireAsync( + const KeyType& key, + CacheCausalConsistency causalConsistency = CacheCausalConsistency::kLatestCached) { // Fast path if (auto cachedValue = _cache.get(key, causalConsistency)) @@ -294,12 +294,11 @@ public: * NOTES: * This is a potentially blocking method. */ - TEMPLATE(typename KeyType) - REQUIRES(IsComparable) - ValueHandle acquire( - OperationContext* opCtx, - const KeyType& key, - CacheCausalConsistency causalConsistency = CacheCausalConsistency::kLatestCached) { + template + requires IsComparable ValueHandle + acquire(OperationContext* opCtx, + const KeyType& key, + CacheCausalConsistency causalConsistency = CacheCausalConsistency::kLatestCached) { return acquireAsync(key, causalConsistency).get(opCtx); } @@ -310,9 +309,8 @@ public: * Doesn't attempt to lookup, and so doesn't block, but this means it will ignore any * in-progress keys or keys whose time in store is newer than what is currently cached. */ - TEMPLATE(typename KeyType) - REQUIRES(IsComparable) - ValueHandle peekLatestCached(const KeyType& key) { + template + requires IsComparable ValueHandle peekLatestCached(const KeyType& key) { return {_cache.get(key, CacheCausalConsistency::kLatestCached)}; } @@ -401,8 +399,8 @@ public: * Returns true if the passed 'newTimeInStore' is greater than the time of the currently cached * value or if no value is cached for 'key'. */ - TEMPLATE(typename KeyType) - REQUIRES(IsComparable) + template + requires IsComparable bool advanceTimeInStore(const KeyType& key, const Time& newTime) { stdx::lock_guard lg(_mutex); if (auto it = _inProgressLookups.find(key); it != _inProgressLookups.end()) @@ -421,8 +419,8 @@ public: * In essence, the invalidate+ calls serve as an externally induced "barrier" for the affected * keys. */ - TEMPLATE(typename KeyType) - REQUIRES(IsComparable) + template + requires IsComparable void invalidateKey(const KeyType& key) { stdx::lock_guard lg(_mutex); if (auto it = _inProgressLookups.find(key); it != _inProgressLookups.end()) diff --git a/src/mongo/util/registry_list.h b/src/mongo/util/registry_list.h index f451cb78a46..26db8b9b04d 100644 --- a/src/mongo/util/registry_list.h +++ b/src/mongo/util/registry_list.h @@ -33,7 +33,6 @@ #include #include "mongo/stdx/mutex.h" -#include "mongo/util/concepts.h" namespace mongo { @@ -87,8 +86,8 @@ private: * This class does no lifetime management for its elements besides construction and destruction. If * you use it to store pointers, the pointed-to memory should be immortal. */ -TEMPLATE(typename ElementT) -REQUIRES(std::is_default_constructible_v) +template +requires std::is_default_constructible_v class RegistryList { public: using ElementType = ElementT; @@ -159,8 +158,8 @@ private: /** * Wrap the basic RegistryList concept to handle weak_ptrs */ -TEMPLATE(typename T) -REQUIRES(std::is_constructible_v>) +template +requires std::is_constructible_v> class WeakPtrRegistryList : public RegistryList> { public: using ElementType = std::weak_ptr; -- cgit v1.2.1