summaryrefslogtreecommitdiff
path: root/AK
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-07-26 16:25:02 +0200
committerAndreas Kling <kling@serenityos.org>2020-07-26 17:51:00 +0200
commitce2c5b375c85667425d4a4198a1f8e23836aa41e (patch)
tree8a63269ffb83bda97f525d8838692ff3ffcee2bc /AK
parenta56512179324f3634ec76314d15345610f593ab2 (diff)
downloadserenity-ce2c5b375c85667425d4a4198a1f8e23836aa41e.zip
AK: Add global is<T>() and downcast<T>()
Let's unify the is<T>/to<T> implementations that currently exist in separate versions in LibCore and LibWeb.
Diffstat (limited to 'AK')
-rw-r--r--AK/StdLibExtras.h21
-rw-r--r--AK/TypeCasts.h93
2 files changed, 114 insertions, 0 deletions
diff --git a/AK/StdLibExtras.h b/AK/StdLibExtras.h
index 67c0f865a4..989aba9d5c 100644
--- a/AK/StdLibExtras.h
+++ b/AK/StdLibExtras.h
@@ -107,10 +107,12 @@ template<class T>
struct RemoveConst {
typedef T Type;
};
+
template<class T>
struct RemoveConst<const T> {
typedef T Type;
};
+
template<class T>
struct RemoveVolatile {
typedef T Type;
@@ -441,6 +443,22 @@ inline constexpr T exchange(T& slot, U&& value)
return old_value;
}
+template<typename T>
+struct IsUnion : public IntegralConstant<bool, __is_union(T)> {
+};
+
+template<typename T>
+struct IsClass : public IntegralConstant<bool, __is_class(T)> {
+};
+
+template<typename Base, typename Derived>
+struct IsBaseOf : public IntegralConstant<bool, __is_base_of(Base, Derived)> {
+};
+
+template<typename ReferenceType, typename T>
+using CopyConst =
+ typename Conditional<IsConst<ReferenceType>::value, typename AddConst<T>::Type, typename RemoveConst<T>::Type>::Type;
+
}
using AK::AddConst;
@@ -449,8 +467,11 @@ using AK::clamp;
using AK::Conditional;
using AK::exchange;
using AK::forward;
+using AK::IsBaseOf;
+using AK::IsClass;
using AK::IsConst;
using AK::IsSame;
+using AK::IsUnion;
using AK::IsVoid;
using AK::MakeSigned;
using AK::MakeUnsigned;
diff --git a/AK/TypeCasts.h b/AK/TypeCasts.h
new file mode 100644
index 0000000000..434da021e6
--- /dev/null
+++ b/AK/TypeCasts.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in input and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of input code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/StdLibExtras.h>
+
+namespace AK {
+
+template<typename OutputType, typename InputType, bool is_base_type = IsBaseOf<OutputType, InputType>::value>
+struct TypeTraits {
+ static bool has_type(InputType&)
+ {
+ static_assert(IsVoid<OutputType>::value, "No TypeTraits for this type");
+ return false;
+ }
+};
+
+template<typename OutputType, typename InputType>
+struct TypeTraits<OutputType, InputType, true> {
+ static bool has_type(InputType&) { return true; }
+};
+
+template<typename OutputType, typename InputType>
+inline bool is(InputType* input)
+{
+ return input && TypeTraits<const OutputType, const InputType>::has_type(*input);
+}
+
+template<typename OutputType, typename InputType>
+inline bool is(InputType& input)
+{
+ return TypeTraits<const OutputType, const InputType>::has_type(input);
+}
+
+template<typename OutputType, typename InputType>
+inline CopyConst<InputType, OutputType>* downcast(InputType* input)
+{
+ static_assert(IsBaseOf<InputType, OutputType>::value);
+ ASSERT(!input || is<OutputType>(*input));
+ return static_cast<CopyConst<InputType, OutputType>*>(input);
+}
+
+template<typename OutputType, typename InputType>
+inline CopyConst<InputType, OutputType>& downcast(InputType& input)
+{
+ static_assert(IsBaseOf<InputType, OutputType>::value);
+ ASSERT(is<OutputType>(input));
+ return static_cast<CopyConst<InputType, OutputType>&>(input);
+}
+
+#define AK_BEGIN_TYPE_TRAITS(ClassName) \
+ namespace AK { \
+ template<typename InputType> \
+ class TypeTraits<const ClassName, InputType, false> { \
+ public: \
+ static bool has_type(InputType& input) { return is_type(input); } \
+ \
+ private:
+
+#define AK_END_TYPE_TRAITS() \
+ } \
+ ; \
+ }
+
+}
+
+using AK::downcast;
+using AK::is;
+using AK::TypeTraits;