1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef MAPLE_UTIL_INCLUDE_SAFE_CAST_H 17 #define MAPLE_UTIL_INCLUDE_SAFE_CAST_H 18 #include "utils/meta.h" 19 20 namespace maple { 21 template <typename ToT> 22 struct SafeCastCondition : public std::false_type { 23 }; 24 25 #define REGISTER_SAFE_CAST(type, condition) \ 26 template <> \ 27 struct SafeCastCondition<type> : public std::true_type { \ 28 template <typename FromT> \ 29 static inline bool DoIt(const FromT &from) \ 30 { \ 31 return (condition); \ 32 } \ 33 } 34 35 namespace impl { 36 template <typename ToT, typename FromT, typename = std::enable_if_t<std::is_base_of<FromT, ToT>::value>> 37 struct InstanceOfImpl { DoItInstanceOfImpl38 static inline bool DoIt(const FromT &from) 39 { 40 return (SafeCastCondition<ToT>::DoIt(from)); 41 } 42 }; 43 44 template <typename ToT, typename FromT> 45 struct InstanceOfImpl<ToT, FromT, typename std::enable_if_t<std::is_base_of<ToT, FromT>::value>> { 46 static inline bool DoIt(const FromT &) 47 { 48 return true; 49 } 50 }; 51 52 template <typename ToT, typename FromT> 53 struct EnabledSafeCast : public utils::meta_or<std::is_base_of<ToT, FromT>, SafeCastCondition<ToT>>::type { 54 }; 55 } // namespace impl 56 57 template <typename ToT, typename FromT, typename = std::enable_if_t<impl::EnabledSafeCast<ToT, FromT>::value>> 58 inline bool instance_of(FromT &from) 59 { 60 return impl::InstanceOfImpl<ToT, FromT>::DoIt(from); 61 } 62 63 template <typename ToT, typename FromT, typename = std::enable_if_t<impl::EnabledSafeCast<ToT, FromT>::value>> 64 inline bool instance_of(FromT *from) 65 { 66 return (from != nullptr && instance_of<ToT>(*from)); 67 } 68 69 template <typename ToT, typename FromT, 70 typename RetT = std::conditional_t< 71 std::is_const<FromT>::value || std::is_const<std::remove_pointer_t<ToT>>::value, 72 std::add_pointer_t<std::add_const_t<std::remove_cv_t<ToT>>>, std::add_pointer_t<std::remove_cv_t<ToT>>>, 73 typename = std::enable_if_t<impl::EnabledSafeCast<ToT, FromT>::value>> 74 inline RetT safe_cast(FromT &from) 75 { 76 return (instance_of<ToT>(from) ? static_cast<RetT>(&from) : nullptr); 77 } 78 79 template <typename ToT, typename FromT, 80 typename RetT = std::conditional_t< 81 std::is_const<FromT>::value || std::is_const<std::remove_pointer_t<ToT>>::value, 82 std::add_pointer_t<std::add_const_t<std::remove_cv_t<ToT>>>, std::add_pointer_t<std::remove_cv_t<ToT>>>, 83 typename = std::enable_if_t<impl::EnabledSafeCast<ToT, FromT>::value>> 84 inline RetT safe_cast(FromT *from) 85 { 86 return (instance_of<ToT>(from) ? static_cast<RetT>(from) : nullptr); 87 } 88 } // namespace maple 89 #endif // MAPLE_UTIL_INCLUDE_SAFE_CAST_H