summaryrefslogtreecommitdiff
path: root/src/mongo/idl
diff options
context:
space:
mode:
authorBilly Donahue <billy.donahue@mongodb.com>2021-04-13 20:52:44 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-04-22 00:00:27 +0000
commit8f4dbd6889eb9534da7af27729aa0c2edea532f0 (patch)
tree9849d0d59ba36bb78f8bed91d9ee23512ea116a7 /src/mongo/idl
parentccca20406141099cf6f778cd01e633ecd1fd8f11 (diff)
downloadmongo-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.h64
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