summaryrefslogtreecommitdiff
path: root/src/mongo/base
diff options
context:
space:
mode:
authorsamantharitter <samantha.ritter@10gen.com>2016-11-07 17:44:02 -0500
committersamantharitter <samantha.ritter@10gen.com>2016-11-08 16:30:37 -0500
commit158db044bb21a2ff39c2984a35850a28c9572c8d (patch)
treefb79dfc17888c9fb456e2fd8c34bd8aef289a3c7 /src/mongo/base
parent17c37d0e626a61aeae8f4f149da98df2496740fa (diff)
downloadmongo-158db044bb21a2ff39c2984a35850a28c9572c8d.tar.gz
SERVER-26674 Add checked_pointer_cast
Diffstat (limited to 'src/mongo/base')
-rw-r--r--src/mongo/base/checked_cast.h37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/mongo/base/checked_cast.h b/src/mongo/base/checked_cast.h
index 94cf5ea9c1f..e434a4c6e12 100644
--- a/src/mongo/base/checked_cast.h
+++ b/src/mongo/base/checked_cast.h
@@ -30,6 +30,8 @@
#pragma once
+#include <memory>
+
#include "mongo/util/assert_util.h"
#include "mongo/util/debug_util.h"
@@ -73,4 +75,39 @@ T checked_cast(const U& u) {
return checked_cast_impl<kDebugBuild>::cast<T>(u);
};
+/**
+ * Similar to static_pointer_cast, but in debug builds uses RTTI to confirm that the cast
+ * is legal at runtime.
+ */
+template <bool>
+struct checked_pointer_cast_impl;
+
+template <>
+struct checked_pointer_cast_impl<false> {
+ template <typename T, typename U>
+ static std::shared_ptr<T> cast(const std::shared_ptr<U>& u) {
+ return std::static_pointer_cast<T>(u);
+ }
+};
+
+template <>
+struct checked_pointer_cast_impl<true> {
+ template <typename T, typename U>
+ static std::shared_ptr<T> cast(const std::shared_ptr<U>& u) {
+ if (!u) {
+ return nullptr;
+ }
+
+ std::shared_ptr<T> t = std::dynamic_pointer_cast<T>(u);
+ invariant(t);
+
+ return t;
+ }
+};
+
+template <typename T, typename U>
+std::shared_ptr<T> checked_pointer_cast(const std::shared_ptr<U>& u) {
+ return checked_pointer_cast_impl<kDebugBuild>::cast<T>(u);
+};
+
} // namespace mongo