summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBilly Donahue <billy.donahue@mongodb.com>2023-05-13 07:47:54 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-05-13 09:06:28 +0000
commitf573501f44fd8cdc479f1ca830f200c693754ff8 (patch)
tree50a8de8286e350f003ba431507d5e83f566a854c
parente317e92c9f1f530c35cb85fc698c3e8dfddd72d4 (diff)
downloadmongo-f573501f44fd8cdc479f1ca830f200c693754ff8.tar.gz
SERVER-48898 replace util/concepts.h with real concepts
-rw-r--r--src/mongo/bson/bsonobjbuilder.h6
-rw-r--r--src/mongo/bson/util/builder.h8
-rw-r--r--src/mongo/db/exec/document_value/value.h14
-rw-r--r--src/mongo/db/query/optimizer/algebra/operator.h18
-rw-r--r--src/mongo/executor/remote_command_request.h12
-rw-r--r--src/mongo/platform/mutex.h5
-rw-r--r--src/mongo/transport/asio/asio_networking_baton.h1
-rw-r--r--src/mongo/unittest/assert.h23
-rw-r--r--src/mongo/util/SConscript1
-rw-r--r--src/mongo/util/concepts.h210
-rw-r--r--src/mongo/util/concepts_test.cpp170
-rw-r--r--src/mongo/util/functional.h15
-rw-r--r--src/mongo/util/future.h251
-rw-r--r--src/mongo/util/future_impl.h51
-rw-r--r--src/mongo/util/future_test_promise_int.cpp1
-rw-r--r--src/mongo/util/future_test_utils.h1
-rw-r--r--src/mongo/util/future_util.h26
-rw-r--r--src/mongo/util/interruptible.h5
-rw-r--r--src/mongo/util/invalidating_lru_cache.h25
-rw-r--r--src/mongo/util/lru_cache.h28
-rw-r--r--src/mongo/util/read_through_cache.h34
-rw-r--r--src/mongo/util/registry_list.h9
22 files changed, 257 insertions, 657 deletions
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<decltype(std::declval<Map>().begin()->first), StringData>)
- Derived& append(StringData fieldName, const Map& map) {
+ template <typename Map>
+ requires std::is_convertible_v<decltype(std::declval<Map>().begin()->first), StringData>
+ Derived& append(StringData fieldName, const Map& map) {
typename std::remove_reference<Derived>::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<int64_t, long long>)
- void appendNum(int64_t j) {
+ template <int...>
+ requires(!std::is_same_v<int64_t, long long>) 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<BufferAllocator, SharedBufferAllocator>)
+ template <int...>
+ requires std::is_same_v<BufferAllocator, SharedBufferAllocator>
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<T>(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<T>)
- ImplicitValue(T&& arg) : Value(std::forward<T>(arg)) {}
+ template <typename T>
+ requires std::is_constructible_v<Value, T> ImplicitValue(T&& arg)
+ : Value(std::forward<T>(arg)) {}
ImplicitValue(std::initializer_list<ImplicitValue> values) : Value(convertToValues(values)) {}
ImplicitValue(std::vector<ImplicitValue> 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 <utility>
#include <vector>
-#include "mongo/util/concepts.h"
-
namespace mongo::optimizer {
namespace algebra {
@@ -66,19 +64,17 @@ class OpFixedArity : public OpNodeStorage<Slot, Arity> {
using Base = OpNodeStorage<Slot, Arity>;
public:
- TEMPLATE(typename... Ts)
- REQUIRES(sizeof...(Ts) == Arity)
- OpFixedArity(Ts&&... vals) : Base({std::forward<Ts>(vals)...}) {}
+ template <typename... Ts>
+ requires(sizeof...(Ts) == Arity) OpFixedArity(Ts&&... vals)
+ : Base({std::forward<Ts>(vals)...}) {}
- TEMPLATE(int I)
- REQUIRES(I >= 0 && I < Arity)
- auto& get() noexcept {
+ template <int I>
+ 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 <int I>
+ 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<Target, std::vector<HostAndPort>>)
- RemoteCommandRequestImpl(const RemoteCommandRequestImpl<HostAndPort>& other)
+ template <int...>
+ requires std::is_same_v<Target, std::vector<HostAndPort>> RemoteCommandRequestImpl(
+ const RemoteCommandRequestImpl<HostAndPort>& 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<Target, HostAndPort>)
- RemoteCommandRequestImpl(const RemoteCommandRequestImpl<std::vector<HostAndPort>>& other,
- size_t idx)
+ template <int...>
+ requires std::is_same_v<Target, HostAndPort> RemoteCommandRequestImpl(
+ const RemoteCommandRequestImpl<std::vector<HostAndPort>>& 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<DiagnosticListener, ListenerT>)
+template <typename ListenerT>
+requires std::is_base_of_v<DiagnosticListener, ListenerT>
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<A, StringData> && std::is_convertible_v<B, StringData>)&& //
- !(std::is_pointer_v<A> && std::is_pointer_v<B>)&& //
- !(std::is_array_v<A> && std::is_array_v<B>))
- static ComparisonAssertion make(const char* theFile,
- unsigned theLine,
- StringData aExpression,
- StringData bExpression,
- const A& a,
- const B& b) {
+
+ template <typename A, typename B>
+ requires( //
+ !(std::is_convertible_v<A, StringData> && std::is_convertible_v<B, StringData>)&& //
+ !(std::is_pointer_v<A> && std::is_pointer_v<B>)&& //
+ !(std::is_array_v<A> && std::is_array_v<B>)) //
+ 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
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * 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 <type_traits>
-
-#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 <typename T> void doThing(T);
-// template <typename T> requires(IsFoo<T>) void doThing(T);
-// template <typename T> requires(IsFoo<T> && IsBar<T>) void doThing(T);
-//
-// With the emulation, you need to explicitly make them all mutually exclusive:
-// template <typename T> requires(!IsFoo<T>) void doThing(T);
-// template <typename T> requires( IsFoo<T> && !IsBar<T>) void doThing(T);
-// template <typename T> requires( IsFoo<T> && IsBar<T>) void doThing(T);
-//
-
-/**
- * Use "TEMPLATE(typename T)" instead of "template <typename T>" 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<Callback, Status>)
- * void registerCallback(Callback&& cb);
- *
- * TEMPLATE(typename Callback)
- * REQUIRES_OUT_OF_LINE_DEF(std::is_invocable_v<Callback, Status>)
- * 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 <typename T>
- * 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 <int... ignoreThisArg> \
- 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_HELPER_EXPAND tpl_params> \
- MONGO_MAKE_BOOL_TRAIT_CONCEPTS_KEYWORD make_trait_impl_##name##_concept = \
- requires(MONGO_MAKE_BOOL_TRAIT_HELPER_EXPAND decls) { \
- {__VA_ARGS__}; \
- }; \
- template <MONGO_MAKE_BOOL_TRAIT_HELPER_EXPAND tpl_params> \
- constexpr inline bool name = \
- make_trait_impl_##name##_concept<MONGO_MAKE_BOOL_TRAIT_HELPER_EXPAND tpl_args>
-
-// 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 <int ignoreThisArg = 0, \
- std::enable_if_t<(__VA_ARGS__), \
- std::enable_if_t<(ignoreThisArg * __LINE__) == 0, int>> = 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 <MONGO_MAKE_BOOL_TRAIT_HELPER_EXPAND tpl_params> \
- auto make_trait_impl_##name##_fn(MONGO_MAKE_BOOL_TRAIT_HELPER_EXPAND decls) \
- ->decltype(__VA_ARGS__); \
- \
- template <typename ALWAYS_VOID, MONGO_MAKE_BOOL_TRAIT_HELPER_EXPAND tpl_params> \
- constexpr inline bool make_trait_impl_##name##_bool = false; \
- \
- template <MONGO_MAKE_BOOL_TRAIT_HELPER_EXPAND tpl_params> \
- 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>)>, \
- MONGO_MAKE_BOOL_TRAIT_HELPER_EXPAND tpl_args> = true; \
- \
- template <MONGO_MAKE_BOOL_TRAIT_HELPER_EXPAND tpl_params> \
- constexpr inline bool name = \
- make_trait_impl_##name##_bool<void, MONGO_MAKE_BOOL_TRAIT_HELPER_EXPAND tpl_args>
-
-#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
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * 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 <boost/preprocessor/cat.hpp>
-#include <cstdint>
-#include <string>
-
-#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 <int num>
-using Overload = std::integral_constant<int, num>;
-
-// Using overload resolution in test to ensure a useful error message.
-#define ASSERT_SELECTS_OVERLOAD(num, ...) \
- int compileTestName(Overload<num>); \
- 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 <typename T>
-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 <typename T>
-constexpr inline auto sizeof_ = sizeof(T);
-
-static_assert(std::is_void_v<decltype(NonTemplateTest<int32_t>::test())>);
-static_assert(std::is_void_v<decltype(NonTemplateTest<int64_t>::test())>);
-ASSERT_DOES_NOT_COMPILE(CharNonTemplateTest, typename Char = char, NonTemplateTest<Char>::test());
-
-// Uncomment to see error message.
-// auto x = NonTemplateTest<char>::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<char>());
-ASSERT_SELECTS_OVERLOAD(3, requiresTest<int32_t>());
-ASSERT_DOES_NOT_COMPILE(Int64RequiresTest, typename Int64_t = int64_t, requiresTest<Int64_t>());
-
-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<i>());
-
-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<int, int>);
-static_assert(isAddable<int, double>);
-static_assert(isAddable<std::string, std::string>);
-static_assert(!isAddable<std::string, int>);
-static_assert(!isAddable<int, std::string>);
-
-
-MONGO_MAKE_BOOL_TRAIT(isCallable,
- (typename Func, typename... Args),
- (Func, Args...),
- (Func & func, Args&&... args),
- //
- func(args...));
-
-static_assert(isCallable<void()>);
-static_assert(!isCallable<void(), int>);
-static_assert(isCallable<void(...)>);
-static_assert(isCallable<void(...), int>);
-static_assert(isCallable<void(...), int, int>);
-static_assert(isCallable<void(StringData), StringData>);
-static_assert(isCallable<void(StringData), const char*>);
-static_assert(isCallable<void(StringData), std::string>);
-static_assert(!isCallable<void(StringData)>);
-static_assert(!isCallable<void(StringData), int>);
-static_assert(!isCallable<void(StringData), StringData, StringData>);
-
-// 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 <typename Function>
@@ -61,10 +60,11 @@ class function_ref;
template <typename RetType, typename... Args>
class function_ref<RetType(Args...)> {
public:
- TEMPLATE(typename F)
- REQUIRES(std::is_invocable_r_v<RetType, F&, Args...> &&
- !std::is_same_v<stdx::remove_cvref_t<F>, function_ref>)
- /*implicit*/ function_ref(F&& f) noexcept {
+ /** Implicitly convertible from any `f` callable with signature `RetType f(Args...)`. */
+ template <typename F>
+ requires(std::is_invocable_r_v<RetType, F&, Args...> &&
+ !std::is_same_v<stdx::remove_cvref_t<F>, 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<std::remove_pointer_t<std::remove_reference_t<F>>>;
@@ -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<std::remove_pointer_t<T>>)
- function_ref& operator=(T) = delete;
+ template <typename T>
+ requires(!std::is_function_v<std::remove_pointer_t<T>>) function_ref& operator=(T) = delete;
RetType operator()(Args... args) const {
return _adapter(_target, std::forward<Args>(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<T>)
+ template <int...>
+ requires std::is_void_v<T>
static SemiFuture<void> makeReady() {
return SemiFuture(Impl::makeReady());
}
@@ -296,9 +297,9 @@ private:
};
// Deduction Guides
-TEMPLATE(typename T)
-REQUIRES(!isStatusOrStatusWith<T> && !future_details::isFutureLike<T>)
-SemiFuture(T)->SemiFuture<T>;
+template <typename T>
+requires(!isStatusOrStatusWith<T> && !future_details::isFutureLike<T>) SemiFuture(T)
+->SemiFuture<T>;
template <typename T>
SemiFuture(StatusWith<T>) -> SemiFuture<T>;
@@ -343,7 +344,8 @@ public:
static Future<T> makeReady(StatusWith<T_unless_void> val) {
return Future(Impl::makeReady(std::move(val)));
}
- REQUIRES_FOR_NON_TEMPLATE(std::is_void_v<T>)
+ template <int...>
+ requires std::is_void_v<T>
static Future<void> 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<void, Func, StatusOrStatusWith<T>>&&
- isFuturePolicy<Policy>)
- void getAsync(Policy policy, Func&& func) && noexcept {
+ template <typename Policy, typename Func>
+ requires(future_details::isCallableExactR<void, Func, StatusOrStatusWith<T>>&&
+ isFuturePolicy<Policy>) void getAsync(Policy policy, Func&& func) && noexcept {
std::move(this->_impl).getAsync(policy, std::forward<Func>(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<Func, T>&& isFuturePolicy<Policy>)
- /*see above*/ auto then(Policy policy, Func&& func) && noexcept {
+ template <typename Policy, typename Func>
+ requires(future_details::isCallable<Func, T>&& isFuturePolicy<Policy>) auto then(
+ Policy policy, Func&& func) && noexcept {
return wrap<Func, T>(std::move(this->_impl).then(policy, std::forward<Func>(func)));
}
@@ -421,9 +422,9 @@ public:
* The callback takes a StatusOrStatusWith<T> and can return anything (see above for how Statusy
* and Futurey returns are handled.)
*/
- TEMPLATE(typename Policy, typename Func)
- REQUIRES(future_details::isCallable<Func, StatusOrStatusWith<T>>&& isFuturePolicy<Policy>)
- /*see above*/ auto onCompletion(Policy policy, Func&& func) && noexcept {
+ template <typename Policy, typename Func>
+ requires(future_details::isCallable<Func, StatusOrStatusWith<T>>&&
+ isFuturePolicy<Policy>) auto onCompletion(Policy policy, Func&& func) && noexcept {
return wrap<Func, Status>(
std::move(this->_impl).onCompletion(policy, std::forward<Func>(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<T, Func, Status>&& isFuturePolicy<Policy>)
- /*see above*/ auto onError(Policy policy, Func&& func) && noexcept {
+ template <typename Policy, typename Func>
+ requires(future_details::isCallableR<T, Func, Status>&& isFuturePolicy<Policy>) auto onError(
+ Policy policy, Func&& func) && noexcept {
return wrap<Func, Status>(std::move(this->_impl).onError(policy, std::forward<Func>(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<T, Func, Status>&& isFuturePolicy<Policy>)
- /*see above*/ auto onError(Policy policy, Func&& func) && noexcept {
+ template <ErrorCodes::Error code, typename Policy, typename Func>
+ requires(future_details::isCallableR<T, Func, Status>&& isFuturePolicy<Policy>) auto onError(
+ Policy policy, Func&& func) && noexcept {
return wrap<Func, Status>(
std::move(this->_impl).template onError<code>(policy, std::forward<Func>(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<T, Func, Status>&& isFuturePolicy<Policy>)
- /*see above*/ auto onErrorCategory(Policy policy, Func&& func) && noexcept {
+ template <ErrorCategory category, typename Policy, typename Func>
+ requires(future_details::isCallableR<T, Func, Status>&&
+ isFuturePolicy<Policy>) auto onErrorCategory(Policy policy,
+ Func&& func) && noexcept {
return wrap<Func, Status>(
std::move(this->_impl)
.template onErrorCategory<category>(policy, std::forward<Func>(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<void, Func, const T>&& isFuturePolicy<Policy>)
- Future<T> tap(Policy policy, Func&& func) && noexcept {
+ template <typename Policy, typename Func>
+ requires(future_details::isCallableExactR<void, Func, const T>&& isFuturePolicy<Policy>)
+ Future<T> tap(Policy policy, Func&& func) && noexcept {
return Future<T>(std::move(this->_impl).tap(policy, std::forward<Func>(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<void, Func, const Status>&& isFuturePolicy<Policy>)
- Future<T> tapError(Policy policy, Func&& func) && noexcept {
+ template <typename Policy, typename Func>
+ requires(future_details::isCallableExactR<void, Func, const Status>&& isFuturePolicy<Policy>)
+ Future<T> tapError(Policy policy, Func&& func) && noexcept {
return Future<T>(std::move(this->_impl).tapError(policy, std::forward<Func>(func)));
}
@@ -523,10 +525,9 @@ public:
*
* The callback takes a StatusOrStatusWith<T> and must return void.
*/
- TEMPLATE(typename Policy, typename Func)
- REQUIRES(future_details::isCallableExactR<void, Func, const StatusOrStatusWith<T>>&&
- isFuturePolicy<Policy>)
- Future<T> tapAll(Policy policy, Func&& func) && noexcept {
+ template <typename Policy, typename Func>
+ requires(future_details::isCallableExactR<void, Func, const StatusOrStatusWith<T>>&&
+ isFuturePolicy<Policy>) Future<T> tapAll(Policy policy, Func&& func) && noexcept {
return Future<T>(std::move(this->_impl).tapAll(policy, std::forward<Func>(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<void, Func, StatusOrStatusWith<T>>)
+ template <typename Func>
+ requires future_details::isCallableExactR<void, Func, StatusOrStatusWith<T>>
void getAsync(Func&& func) && noexcept {
std::move(*this).getAsync(destroyDefault, std::forward<Func>(func));
}
- TEMPLATE(typename Func)
- REQUIRES(future_details::isCallable<Func, T>)
+ template <typename Func>
+ requires future_details::isCallable<Func, T>
auto then(Func&& func) && noexcept {
return std::move(*this).then(destroyDefault, std::forward<Func>(func));
}
- TEMPLATE(typename Func)
- REQUIRES(future_details::isCallable<Func, StatusOrStatusWith<T>>)
+ template <typename Func>
+ requires future_details::isCallable<Func, StatusOrStatusWith<T>>
auto onCompletion(Func&& func) && noexcept {
return std::move(*this).onCompletion(destroyDefault, std::forward<Func>(func));
}
- TEMPLATE(typename Func)
- REQUIRES(future_details::isCallableR<T, Func, Status>)
+ template <typename Func>
+ requires future_details::isCallableR<T, Func, Status>
auto onError(Func&& func) && noexcept {
return std::move(*this).onError(destroyDefault, std::forward<Func>(func));
}
- TEMPLATE(ErrorCodes::Error code, typename Func)
- REQUIRES(future_details::isCallableR<T, Func, Status>)
+ template <ErrorCodes::Error code, typename Func>
+ requires future_details::isCallableR<T, Func, Status>
auto onError(Func&& func) && noexcept {
return std::move(*this).template onError<code>(destroyDefault, std::forward<Func>(func));
}
- TEMPLATE(ErrorCategory category, typename Func)
- REQUIRES(future_details::isCallableR<T, Func, Status>)
+ template <ErrorCategory category, typename Func>
+ requires future_details::isCallableR<T, Func, Status>
auto onErrorCategory(Func&& func) && noexcept {
return std::move(*this).template onErrorCategory<category>(destroyDefault,
std::forward<Func>(func));
}
- TEMPLATE(typename Func)
- REQUIRES(future_details::isCallableExactR<void, Func, const T>)
- Future<T> tap(Func&& func) && noexcept {
+ template <typename Func>
+ requires future_details::isCallableExactR<void, Func, const T> Future<T> tap(
+ Func&& func) && noexcept {
return std::move(*this).tap(destroyDefault, std::forward<Func>(func));
}
- TEMPLATE(typename Func)
- REQUIRES(future_details::isCallableExactR<void, Func, const Status>)
- Future<T> tapError(Func&& func) && noexcept {
+ template <typename Func>
+ requires future_details::isCallableExactR<void, Func, const Status> Future<T> tapError(
+ Func&& func) && noexcept {
return std::move(*this).tapError(destroyDefault, std::forward<Func>(func));
}
- TEMPLATE(typename Func)
- REQUIRES(future_details::isCallableExactR<void, Func, const StatusOrStatusWith<T>>)
- Future<T> tapAll(Func&& func) && noexcept {
+ template <typename Func>
+ requires future_details::isCallableExactR<void, Func, const StatusOrStatusWith<T>> Future<T>
+ tapAll(Func&& func) && noexcept {
return std::move(*this).tapAll(destroyDefault, std::forward<Func>(func));
}
@@ -607,9 +608,9 @@ private:
};
// Deduction Guides
-TEMPLATE(typename T)
-REQUIRES(!isStatusOrStatusWith<T> && !future_details::isFutureLike<T>)
-Future(T)->Future<T>;
+template <typename T>
+requires(!isStatusOrStatusWith<T> && !future_details::isFutureLike<T>) Future(T)
+->Future<T>;
template <typename T>
Future(StatusWith<T>) -> Future<T>;
@@ -649,7 +650,8 @@ public:
static_assert(!std::is_void_v<T>);
}
- REQUIRES_FOR_NON_TEMPLATE(std::is_void_v<T>)
+ template <int...>
+ requires std::is_void_v<T>
explicit ExecutorFuture(ExecutorPtr exec) : SemiFuture<void>(), _exec(std::move(exec)) {}
/**
@@ -690,10 +692,9 @@ public:
* Attach a completion callback to asynchronously consume this `ExecutorFuture`'s result.
* \see `Future<T>::getAsync()`.
*/
- TEMPLATE(typename Policy, typename Func)
- REQUIRES(future_details::isCallableExactR<void, Func, StatusOrStatusWith<T>>&&
- isFuturePolicy<Policy>)
- void getAsync(Policy policy, Func&& func) && noexcept {
+ template <typename Policy, typename Func>
+ requires(future_details::isCallableExactR<void, Func, StatusOrStatusWith<T>>&&
+ isFuturePolicy<Policy>) void getAsync(Policy policy, Func&& func) && noexcept {
static_assert(std::is_void_v<decltype(func(std::declval<StatusOrStatusWith<T>>()))>,
"func passed to getAsync must return void");
@@ -713,17 +714,17 @@ public:
});
}
- TEMPLATE(typename Policy, typename Func)
- REQUIRES(future_details::isCallable<Func, T>&& isFuturePolicy<Policy>)
- auto then(Policy policy, Func&& func) && noexcept {
+ template <typename Policy, typename Func>
+ requires(future_details::isCallable<Func, T>&& isFuturePolicy<Policy>) auto then(
+ Policy policy, Func&& func) && noexcept {
return mongo::ExecutorFuture(
std::move(_exec),
std::move(this->_impl).then(policy, wrapCB<T>(policy, std::forward<Func>(func))));
}
- TEMPLATE(typename Policy, typename Func)
- REQUIRES(future_details::isCallable<Func, StatusOrStatusWith<T>>&& isFuturePolicy<Policy>)
- auto onCompletion(Policy policy, Func&& func) && noexcept {
+ template <typename Policy, typename Func>
+ requires(future_details::isCallable<Func, StatusOrStatusWith<T>>&&
+ isFuturePolicy<Policy>) auto onCompletion(Policy policy, Func&& func) && noexcept {
return mongo::ExecutorFuture(
std::move(_exec),
std::move(this->_impl)
@@ -731,27 +732,27 @@ public:
wrapCB<StatusOrStatusWith<T>>(policy, std::forward<Func>(func))));
}
- TEMPLATE(typename Policy, typename Func)
- REQUIRES(future_details::isCallableR<T, Func, Status>&& isFuturePolicy<Policy>)
- ExecutorFuture<T> onError(Policy policy, Func&& func) && noexcept {
+ template <typename Policy, typename Func>
+ requires(future_details::isCallableR<T, Func, Status>&& isFuturePolicy<Policy>)
+ ExecutorFuture<T> onError(Policy policy, Func&& func) && noexcept {
return mongo::ExecutorFuture(
std::move(_exec),
std::move(this->_impl)
.onError(policy, wrapCB<Status>(policy, std::forward<Func>(func))));
}
- TEMPLATE(ErrorCodes::Error code, typename Policy, typename Func)
- REQUIRES(future_details::isCallableR<T, Func, Status>&& isFuturePolicy<Policy>)
- ExecutorFuture<T> onError(Policy policy, Func&& func) && noexcept {
+ template <ErrorCodes::Error code, typename Policy, typename Func>
+ requires(future_details::isCallableR<T, Func, Status>&& isFuturePolicy<Policy>)
+ ExecutorFuture<T> onError(Policy policy, Func&& func) && noexcept {
return mongo::ExecutorFuture(
std::move(_exec),
std::move(this->_impl)
.template onError<code>(policy, wrapCB<Status>(policy, std::forward<Func>(func))));
}
- TEMPLATE(ErrorCategory category, typename Policy, typename Func)
- REQUIRES(future_details::isCallableR<T, Func, Status>&& isFuturePolicy<Policy>)
- ExecutorFuture<T> onErrorCategory(Policy policy, Func&& func) && noexcept {
+ template <ErrorCategory category, typename Policy, typename Func>
+ requires(future_details::isCallableR<T, Func, Status>&& isFuturePolicy<Policy>)
+ ExecutorFuture<T> 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<void, Func, StatusOrStatusWith<T>>)
+ template <typename Func>
+ requires future_details::isCallableExactR<void, Func, StatusOrStatusWith<T>>
void getAsync(Func&& func) && noexcept {
std::move(*this).getAsync(destroyDefault, std::forward<Func>(func));
}
- TEMPLATE(typename Func)
- REQUIRES(future_details::isCallable<Func, T>)
+ template <typename Func>
+ requires future_details::isCallable<Func, T>
auto then(Func&& func) && noexcept {
return std::move(*this).then(destroyDefault, std::forward<Func>(func));
}
- TEMPLATE(typename Func)
- REQUIRES(future_details::isCallable<Func, StatusOrStatusWith<T>>)
+ template <typename Func>
+ requires future_details::isCallable<Func, StatusOrStatusWith<T>>
auto onCompletion(Func&& func) && noexcept {
return std::move(*this).onCompletion(destroyDefault, std::forward<Func>(func));
}
- TEMPLATE(typename Func)
- REQUIRES(future_details::isCallableR<T, Func, Status>)
+ template <typename Func>
+ requires future_details::isCallableR<T, Func, Status>
auto onError(Func&& func) && noexcept {
return std::move(*this).onError(destroyDefault, std::forward<Func>(func));
}
- TEMPLATE(ErrorCodes::Error code, typename Func)
- REQUIRES(future_details::isCallableR<T, Func, Status>)
+ template <ErrorCodes::Error code, typename Func>
+ requires future_details::isCallableR<T, Func, Status>
auto onError(Func&& func) && noexcept {
return std::move(*this).template onError<code>(destroyDefault, std::forward<Func>(func));
}
- TEMPLATE(ErrorCategory category, typename Func)
- REQUIRES(future_details::isCallableR<T, Func, Status>)
+ template <ErrorCategory category, typename Func>
+ requires future_details::isCallableR<T, Func, Status>
auto onErrorCategory(Func&& func) && noexcept {
return std::move(*this).template onErrorCategory<category>(destroyDefault,
std::forward<Func>(func));
@@ -816,8 +817,8 @@ private:
* Future<U>, 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<Policy>)
+ template <typename RawArg, typename Policy, typename Func>
+ requires isFuturePolicy<Policy>
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<std::is_void_v<RawArg>,
@@ -848,9 +849,10 @@ private:
};
// Deduction Guides
-TEMPLATE(typename T)
-REQUIRES(!isStatusOrStatusWith<T> && !future_details::isFutureLike<T>)
-ExecutorFuture(ExecutorPtr, T)->ExecutorFuture<T>;
+template <typename T>
+requires(!isStatusOrStatusWith<T> && !future_details::isFutureLike<T>)
+ ExecutorFuture(ExecutorPtr, T)
+->ExecutorFuture<T>;
template <typename T>
ExecutorFuture(ExecutorPtr, future_details::FutureImpl<T>) -> ExecutorFuture<T>;
template <typename T>
@@ -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<T, Func, void>&& isFuturePolicy<Policy>)
- void setWith(Policy policy, Func&& func) noexcept {
+ template <typename Policy, typename Func>
+ requires(future_details ::isCallableR<T, Func, void>&& isFuturePolicy<Policy>) void setWith(
+ Policy policy, Func&& func) noexcept {
setFrom(Future<void>::makeReady().then(policy, std::forward<Func>(func)));
}
- TEMPLATE(typename Func)
- REQUIRES(future_details::isCallableR<T, Func, void>)
+ template <typename Func>
+ requires future_details::isCallableR<T, Func, void>
void setWith(Func&& func) noexcept {
setWith(destroyDefault, std::forward<Func>(func));
}
@@ -962,16 +964,16 @@ public:
}
// Use emplaceValue(Args&&...) instead.
- REQUIRES_FOR_NON_TEMPLATE(!std::is_void_v<T>)
- void setFrom(T_unless_void val) noexcept = delete;
+ template <int...>
+ requires(!std::is_void_v<T>) void setFrom(T_unless_void val) noexcept = delete;
// Use setError(Status) instead.
- REQUIRES_FOR_NON_TEMPLATE(!std::is_void_v<T>)
- void setFrom(Status) noexcept = delete;
+ template <int...>
+ requires(!std::is_void_v<T>) void setFrom(Status) noexcept = delete;
- TEMPLATE(typename... Args)
- REQUIRES(std::is_constructible_v<T, Args...> || (std::is_void_v<T> && sizeof...(Args) == 0))
- void emplaceValue(Args&&... args) noexcept {
+ template <typename... Args>
+ requires std::is_constructible_v<T, Args...> ||
+ (std::is_void_v<T> && sizeof...(Args) == 0) void emplaceValue(Args&&... args) noexcept {
setImpl([&](boost::intrusive_ptr<SharedStateT>&& sharedState) {
sharedState->emplaceValue(std::forward<Args>(args)...);
});
@@ -1167,9 +1169,9 @@ private:
};
// Deduction Guides
-TEMPLATE(typename T)
-REQUIRES(!isStatusOrStatusWith<T> && !future_details::isFutureLike<T>)
-SharedSemiFuture(T)->SharedSemiFuture<T>;
+template <typename T>
+requires(!isStatusOrStatusWith<T> && !future_details::isFutureLike<T>) SharedSemiFuture(T)
+->SharedSemiFuture<T>;
template <typename T>
SharedSemiFuture(StatusWith<T>) -> SharedSemiFuture<T>;
@@ -1221,13 +1223,13 @@ public:
return SharedSemiFuture<T>(_sharedState);
}
- TEMPLATE(typename Policy, typename Func)
- REQUIRES(future_details::isCallableR<T, Func, void>&& isFuturePolicy<Policy>)
- void setWith(Policy policy, Func&& func) noexcept {
+ template <typename Policy, typename Func>
+ requires(future_details::isCallableR<T, Func, void>&& isFuturePolicy<Policy>) void setWith(
+ Policy policy, Func&& func) noexcept {
setFrom(Future<void>::makeReady().then(policy, std::forward<Func>(func)));
}
- TEMPLATE(typename Func)
- REQUIRES(future_details::isCallableR<T, Func, void>)
+ template <typename Func>
+ requires future_details::isCallableR<T, Func, void>
void setWith(Func&& func) noexcept {
setWith(destroyDefault, std::forward<Func>(func));
}
@@ -1252,16 +1254,17 @@ public:
}
// Use emplaceValue(Args&&...) instead.
- REQUIRES_FOR_NON_TEMPLATE(!std::is_void_v<T>)
- void setFrom(T_unless_void val) noexcept = delete;
+ template <int...>
+ requires(!std ::is_void_v<T>) void setFrom(T_unless_void val) noexcept = delete;
// Use setError(Status) instead.
- REQUIRES_FOR_NON_TEMPLATE(!std::is_void_v<T>)
- void setFrom(Status) noexcept = delete;
+ template <int...>
+ requires(!std ::is_void_v<T>) void setFrom(Status) noexcept = delete;
- TEMPLATE(typename... Args)
- REQUIRES(std::is_constructible_v<T, Args...> || (std::is_void_v<T> && sizeof...(Args) == 0))
- void emplaceValue(Args&&... args) noexcept {
+ template <typename... Args>
+ requires(std::is_constructible_v<T, Args...> ||
+ (std::is_void_v<T> &&
+ sizeof...(Args) == 0)) void emplaceValue(Args&&... args) noexcept {
invariant(!std::exchange(_haveCompleted, true));
_sharedState->emplaceValue(std::forward<Args>(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<Func, void>)
+template <typename Func>
+requires future_details::isCallable<Func, void>
auto makeReadyFutureWith(Func&& func) -> Future<FutureContinuationResult<Func&&>> try {
if constexpr (std::is_void_v<std::invoke_result_t<Func>>) {
std::forward<Func>(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<T, FakeVoid>)
+ template <int...>
+ requires std::is_same_v<T, FakeVoid>
void setFrom(Status status) {
if (status.isOK()) {
emplaceValue();
@@ -942,8 +943,8 @@ public:
return _shared.getNoThrow(interruptible);
}
- TEMPLATE(typename Policy, typename Func)
- REQUIRES(isFuturePolicy<Policy>)
+ template <typename Policy, typename Func>
+ requires isFuturePolicy<Policy>
void getAsync(Policy policy, Func&& func) && noexcept {
static_assert(std::is_void<decltype(call(func, std::declval<StatusWith<T>>()))>::value,
"func passed to getAsync must return void");
@@ -967,8 +968,8 @@ public:
});
}
- TEMPLATE(typename Policy, typename Func)
- REQUIRES(isFuturePolicy<Policy>)
+ template <typename Policy, typename Func>
+ requires isFuturePolicy<Policy>
auto then(Policy policy, Func&& func) && noexcept {
using Result = NormalizedCallResult<Func, T>;
if constexpr (!isFutureLike<Result>) {
@@ -1025,8 +1026,8 @@ public:
}
}
- TEMPLATE(typename Policy, typename Func)
- REQUIRES(isFuturePolicy<Policy>)
+ template <typename Policy, typename Func>
+ requires isFuturePolicy<Policy>
auto onCompletion(Policy policy, Func&& func) && noexcept {
using Wrapper = StatusOrStatusWith<T>;
using Result = NormalizedCallResult<Func, StatusOrStatusWith<T>>;
@@ -1103,9 +1104,9 @@ public:
}
}
- TEMPLATE(typename Policy, typename Func)
- REQUIRES(isFuturePolicy<Policy>)
- FutureImpl<FakeVoidToVoid<T>> onError(Policy policy, Func&& func) && noexcept {
+ template <typename Policy, typename Func>
+ requires isFuturePolicy<Policy> FutureImpl<FakeVoidToVoid<T>> onError(Policy policy,
+ Func&& func) && noexcept {
using Result = NormalizedCallResult<Func, Status>;
static_assert(
std::is_same<VoidToFakeVoid<UnwrappedType<Result>>, T>::value,
@@ -1160,9 +1161,9 @@ public:
}
}
- TEMPLATE(ErrorCodes::Error code, typename Policy, typename Func)
- REQUIRES(isFuturePolicy<Policy>)
- FutureImpl<FakeVoidToVoid<T>> onError(Policy policy, Func&& func) && noexcept {
+ template <ErrorCodes::Error code, typename Policy, typename Func>
+ requires isFuturePolicy<Policy> FutureImpl<FakeVoidToVoid<T>> onError(Policy policy,
+ Func&& func) && noexcept {
using Result = NormalizedCallResult<Func, Status>;
static_assert(
std::is_same_v<UnwrappedType<Result>, FakeVoidToVoid<T>>,
@@ -1181,9 +1182,9 @@ public:
});
}
- TEMPLATE(ErrorCategory category, typename Policy, typename Func)
- REQUIRES(isFuturePolicy<Policy>)
- FutureImpl<FakeVoidToVoid<T>> onErrorCategory(Policy policy, Func&& func) && noexcept {
+ template <ErrorCategory category, typename Policy, typename Func>
+ requires isFuturePolicy<Policy> FutureImpl<FakeVoidToVoid<T>> onErrorCategory(
+ Policy policy, Func&& func) && noexcept {
using Result = NormalizedCallResult<Func, Status>;
static_assert(std::is_same_v<UnwrappedType<Result>, FakeVoidToVoid<T>>,
"func passed to Future<T>::onErrorCategory must return T, StatusWith<T>, "
@@ -1200,9 +1201,9 @@ public:
});
}
- TEMPLATE(typename Policy, typename Func)
- REQUIRES(isFuturePolicy<Policy>)
- FutureImpl<FakeVoidToVoid<T>> tap(Policy policy, Func&& func) && noexcept {
+ template <typename Policy, typename Func>
+ requires isFuturePolicy<Policy> FutureImpl<FakeVoidToVoid<T>> tap(Policy policy,
+ Func&& func) && noexcept {
static_assert(std::is_void<decltype(call(func, std::declval<const T&>()))>::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<Policy>)
- FutureImpl<FakeVoidToVoid<T>> tapError(Policy policy, Func&& func) && noexcept {
+ template <typename Policy, typename Func>
+ requires isFuturePolicy<Policy> FutureImpl<FakeVoidToVoid<T>> tapError(
+ Policy policy, Func&& func) && noexcept {
static_assert(std::is_void<decltype(call(func, std::declval<const Status&>()))>::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<Policy>)
- FutureImpl<FakeVoidToVoid<T>> tapAll(Policy policy, Func&& func) && noexcept {
+ template <typename Policy, typename Func>
+ requires isFuturePolicy<Policy> FutureImpl<FakeVoidToVoid<T>> tapAll(Policy policy,
+ Func&& func) && noexcept {
static_assert(
std::is_void<decltype(call(func, std::declval<const StatusOrStatusWith<T>&>()))>::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<Value>)
-REQUIRES(!std::is_void_v<Value> && future_util_details::isFutureOrExecutorFuture<FutureLike>)
-SemiFuture<ResultVector> whenAllSucceed(std::vector<FutureLike>&& futures) {
+template <typename FutureLike,
+ typename Value = typename FutureLike::value_type,
+ typename ResultVector = std::vector<Value>>
+requires(!std::is_void_v<Value> && future_util_details::isFutureOrExecutorFuture<FutureLike>)
+ SemiFuture<ResultVector> whenAllSucceed(std::vector<FutureLike>&& futures) {
invariant(futures.size() > 0, future_util_details::kWhenAllSucceedEmptyInputInvariantMsg);
// A structure used to share state between the input futures.
@@ -559,9 +559,9 @@ SemiFuture<ResultVector> whenAllSucceed(std::vector<FutureLike>&& futures) {
* Variant of whenAllSucceed for void input futures. The only behavior difference is that it returns
* SemiFuture<void> instead of SemiFuture<std::vector<T>>.
*/
-TEMPLATE(typename FutureLike, typename Value = typename FutureLike::value_type)
-REQUIRES(std::is_void_v<Value>&& future_util_details::isFutureOrExecutorFuture<FutureLike>)
-SemiFuture<void> whenAllSucceed(std::vector<FutureLike>&& futures) {
+template <typename FutureLike, typename Value = typename FutureLike::value_type>
+requires(std::is_void_v<Value>&& future_util_details::isFutureOrExecutorFuture<FutureLike>)
+ SemiFuture<void> whenAllSucceed(std::vector<FutureLike>&& futures) {
invariant(futures.size() > 0, future_util_details::kWhenAllSucceedEmptyInputInvariantMsg);
// A structure used to share state between the input futures.
@@ -714,11 +714,11 @@ SemiFuture<Result> whenAny(std::vector<FutureT>&& 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<FuturePack...>,
- typename Value = typename FutureLike::value_type,
- typename ResultVector = std::vector<Value>)
-REQUIRES(future_util_details::isFutureOrExecutorFuture<FutureLike>)
+template <typename... FuturePack,
+ typename FutureLike = std::common_type_t<FuturePack...>,
+ typename Value = typename FutureLike::value_type,
+ typename ResultVector = std::vector<Value>>
+requires future_util_details::isFutureOrExecutorFuture<FutureLike>
auto whenAllSucceed(FuturePack&&... futures) {
return whenAllSucceed(
future_util_details::variadicArgsToVector(std::forward<FuturePack>(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<latch_detail::Latch, LatchT>) //
+ template <typename LatchT>
+ requires std::is_base_of_v<latch_detail::Latch, LatchT>
static StringData getLatchName(const stdx::unique_lock<LatchT>& 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<KeyType>)
- ValueHandle get(
- const KeyType& key,
+ template <typename KeyType>
+ requires IsComparable<KeyType> ValueHandle
+ get(const KeyType& key,
CacheCausalConsistency causalConsistency = CacheCausalConsistency::kLatestCached) {
stdx::lock_guard<Latch> lg(_mutex);
std::shared_ptr<StoredValue> 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<KeyType>)
+ template <typename KeyType>
+ requires IsComparable<KeyType>
bool advanceTimeInStore(const KeyType& key, const Time& newTimeInStore) {
stdx::lock_guard<Latch> lg(_mutex);
std::shared_ptr<StoredValue> 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<KeyType>)
- std::pair<ValueHandle, Time> getCachedValueAndTimeInStore(const KeyType& key) {
+ template <typename KeyType>
+ requires IsComparable<KeyType> std::pair<ValueHandle, Time> getCachedValueAndTimeInStore(
+ const KeyType& key) {
stdx::lock_guard<Latch> lg(_mutex);
std::shared_ptr<StoredValue> 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<KeyType>)
+ template <typename KeyType>
+ requires IsComparable<KeyType>
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<KeyType>)
+ template <typename KeyType>
+ requires IsComparable<KeyType>
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<KeyType>)
- iterator find(const KeyType& key) {
+ template <typename KeyType>
+ requires IsComparable<KeyType> 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<KeyType>)
- const_iterator cfind(const KeyType& key) const {
+ template <typename KeyType>
+ requires IsComparable<KeyType> 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<KeyType>)
- iterator promote(const KeyType& key) {
+ template <typename KeyType>
+ requires IsComparable<KeyType> 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<KeyType>)
+ template <typename KeyType>
+ requires IsComparable<KeyType>
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<KeyType>)
+ template <typename KeyType>
+ requires IsComparable<KeyType>
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<KeyType>)
+ template <typename KeyType>
+ requires IsComparable<KeyType>
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<KeyType>&& std::is_constructible_v<Key, KeyType>)
- SharedSemiFuture<ValueHandle> acquireAsync(
- const KeyType& key,
- CacheCausalConsistency causalConsistency = CacheCausalConsistency::kLatestCached) {
+ template <typename KeyType>
+ requires(IsComparable<KeyType>&& std::is_constructible_v<Key, KeyType>)
+ SharedSemiFuture<ValueHandle> 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<KeyType>)
- ValueHandle acquire(
- OperationContext* opCtx,
- const KeyType& key,
- CacheCausalConsistency causalConsistency = CacheCausalConsistency::kLatestCached) {
+ template <typename KeyType>
+ requires IsComparable<KeyType> 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<KeyType>)
- ValueHandle peekLatestCached(const KeyType& key) {
+ template <typename KeyType>
+ requires IsComparable<KeyType> 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<KeyType>)
+ template <typename KeyType>
+ requires IsComparable<KeyType>
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<KeyType>)
+ template <typename KeyType>
+ requires IsComparable<KeyType>
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 <memory>
#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<ElementT>)
+template <typename ElementT>
+requires std::is_default_constructible_v<ElementT>
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<std::weak_ptr<T>>)
+template <typename T>
+requires std::is_constructible_v<std::weak_ptr<T>>
class WeakPtrRegistryList : public RegistryList<std::weak_ptr<T>> {
public:
using ElementType = std::weak_ptr<T>;