diff options
author | Billy Donahue <billy.donahue@mongodb.com> | 2021-04-13 20:52:44 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-04-22 00:00:27 +0000 |
commit | 8f4dbd6889eb9534da7af27729aa0c2edea532f0 (patch) | |
tree | 9849d0d59ba36bb78f8bed91d9ee23512ea116a7 /src/mongo/idl | |
parent | ccca20406141099cf6f778cd01e633ecd1fd8f11 (diff) | |
download | mongo-8f4dbd6889eb9534da7af27729aa0c2edea532f0.tar.gz |
SERVER-43964 UUID etc need not befriend IDL types
Diffstat (limited to 'src/mongo/idl')
-rw-r--r-- | src/mongo/idl/idl_parser.h | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/src/mongo/idl/idl_parser.h b/src/mongo/idl/idl_parser.h index 316ccd06c7e..17d7c803586 100644 --- a/src/mongo/idl/idl_parser.h +++ b/src/mongo/idl/idl_parser.h @@ -37,6 +37,7 @@ #include "mongo/bson/bsonobjbuilder.h" #include "mongo/bson/bsontypes.h" #include "mongo/db/namespace_string.h" +#include "mongo/stdx/type_traits.h" namespace mongo { @@ -70,6 +71,69 @@ void idlSerialize(BSONObjBuilder* builder, StringData fieldName, std::vector<T> } } +/** + * A few overloads of `idlPreparsedValue` are built into IDL. See + * `preparsedValue` below. They are placed into a tiny private + * namespace which defines no types to isolate them. + */ +namespace preparsed_value_adl_barrier { + +/** + * This is the fallback for `idlPreparsedValue`. It value-initializes a `T` + * with a forwarded argument list in the usual way. + */ +template <typename T, typename... A> +auto idlPreparsedValue(stdx::type_identity<T>, A&&... a) { + return T(std::forward<A>(a)...); +} + +/** + * The value -1 is a conspicuous "uninitialized" value for integers. + * The integral type `bool` is exempt from this convention, however. + */ +template <typename T, std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<bool, T>, int> = 0> +auto idlPreparsedValue(stdx::type_identity<T>) { + return static_cast<T>(-1); +} + +/** + * Define a default Feature Compatibility Version enum value for use in parsed + * ServerGlobalParams. + * TODO(SERVER-50101): Remove 'FeatureCompatibility::Version' once IDL supports + * a command cpp_type of C++ enum. + */ +inline auto idlPreparsedValue( + stdx::type_identity<ServerGlobalParams::FeatureCompatibility::Version>) { + return ServerGlobalParams::FeatureCompatibility::Version::kUnsetDefault44Behavior; +} + +} // namespace preparsed_value_adl_barrier + +/** + * Constructs an instance of `T(args...)` for use in idl parsing. The way the + * IDL generator currently writes C++ parse functions, it makes an instance of + * a field of type `T` and then mutates it. `preparsedValue<T>()` is used to + * construct those objects. This convention allows an extension hook whereby a + * type can select a custom initializer for such pre-parsed objects, + * particularly for types that shouldn't have a public default constructor. + * + * The extension hook is implemented via ADL on the name `idlPreparsedValue`. + * + * `idlPreparsedValue` takes a `type_identity<T>` and then some forwarded + * constructor arguments optionally (the IDL generator doesn't currently + * provide any such arguments but could conceivably do so in the future). A + * type `T` is deduced from this `type_identity<T>` argument. + * + * There are other ways to implement this extension mechanism, but this + * phrasing allows argument-dependent lookup to search the namespaces + * associated with `T`, since `T` is a template parameter of the + * `type_identity<T>` argument. + */ +template <typename T, typename... A> +T preparsedValue(A&&... args) { + using preparsed_value_adl_barrier::idlPreparsedValue; + return idlPreparsedValue(stdx::type_identity<T>{}, std::forward<A>(args)...); +} } // namespace idl |