// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #pragma once #include namespace ir { /// /// \brief The template function actually called by isa_wrap. /// template struct isa_impl { static inline bool call(const From &Val) { return Target::classof(Val); } }; template struct isa_impl< Target, From, typename std::enable_if::value>::type> { static inline bool call(const From &) { return true; } }; /// /// \brief The template function actually called by isa. /// template struct isa_wrap { static inline bool call(const From &Val) { return isa_impl::call(Val); } }; /// /// \brief typequalified specialization of the isa_wrap template parameter From. /// Specialized types include: const T, T*, const T*, T* const, const T* const. /// template struct isa_wrap { static inline bool call(const From &Val) { return isa_impl::call(Val); } }; template struct isa_wrap< Target, From, typename std::enable_if_t>::value>> { static inline bool call( std::remove_pointer_t> const *Val) { if (Val == nullptr) { throw("isa<> used on a null pointer"); } return isa_impl>>::call( *Val); } }; /// /// \brief isa template function, used to determine whether the value is a /// Target type. Using method: if (isa(value)) { ... }. /// template inline bool isa(const From &Val) { return isa_wrap::type, From>::call(Val); } /// /// \brief Derive cast return type by template parameter From and To. /// template struct ReturnTypeDuductionWrap { typedef To &type; }; template struct ReturnTypeDuductionWrap { typedef const To &type; }; template struct ReturnTypeDuductionWrap { typedef To *type; }; template struct ReturnTypeDuductionWrap { typedef const To *type; }; template struct ReturnTypeDuductionWrap { typedef const To *type; }; template struct ReturnTypeDuduction { typedef typename ReturnTypeDuductionWrap::type type; }; /// /// cast From to To /// template struct cast_impl { // This _is_ a simple type, just cast it. static typename ReturnTypeDuduction::type call(const From &Val) { typename ReturnTypeDuduction::type ret = (typename ReturnTypeDuduction::type) const_cast(Val); return ret; } }; template inline typename ReturnTypeDuduction::type cast(From &Val) { // NOLINT if (!isa(Val)) { throw("cast() argument of incompatible type!"); } return cast_impl::call(Val); } template inline typename ReturnTypeDuduction::type cast(From *Val) { if (!isa(Val)) { throw("cast() argument of incompatible type!"); } return cast_impl::call(Val); } /// /// \brief dyn_cast From to To. /// template inline std::decay_t::type> dyn_cast( From &Val) { // NOLINT return isa(Val) ? cast(Val) : nullptr; } template inline typename ReturnTypeDuduction::type dyn_cast(From *Val) { return isa(Val) ? cast(Val) : nullptr; } } // namespace ir