diff options
author | Andreas Kling <kling@serenityos.org> | 2020-07-26 16:25:02 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-07-26 17:51:00 +0200 |
commit | ce2c5b375c85667425d4a4198a1f8e23836aa41e (patch) | |
tree | 8a63269ffb83bda97f525d8838692ff3ffcee2bc /AK | |
parent | a56512179324f3634ec76314d15345610f593ab2 (diff) | |
download | serenity-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.h | 21 | ||||
-rw-r--r-- | AK/TypeCasts.h | 93 |
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; |