Files
paddlepaddle--paddle/paddle/pir/include/core/cast_utils.h
T
2026-07-13 12:40:42 +08:00

185 lines
5.1 KiB
C++

// 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 <memory>
#include <type_traits>
namespace pir {
///
/// \brief The template function actually called by isa_wrap.
///
template <typename Target, typename From, typename Enabler = void>
struct isa_impl {
static inline bool call(const From &Val) { return Target::classof(Val); }
};
template <typename Target, typename From>
struct isa_impl<
Target,
From,
typename std::enable_if<std::is_base_of<Target, From>::value>::type> {
static inline bool call(const From &) { return true; }
};
///
/// \brief The template function actually called by isa.
///
template <typename Target, typename From, typename Enable = void>
struct isa_wrap {
static inline bool call(const From &Val) {
return isa_impl<Target, From>::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 <typename Target, typename From>
struct isa_wrap<Target, const From> {
static inline bool call(const From &Val) {
return isa_impl<Target, From>::call(Val);
}
};
template <typename Target, typename From>
struct isa_wrap<
Target,
From,
typename std::enable_if_t<std::is_pointer<std::decay_t<From>>::value>> {
static inline bool call(
std::remove_pointer_t<std::decay_t<From>> const *Val) {
if (Val == nullptr) {
throw("isa<> used on a null pointer");
}
return isa_impl<Target, std::remove_pointer_t<std::decay_t<From>>>::call(
*Val);
}
};
///
/// \brief isa template function, used to determine whether the value is a
/// Target type. Using method: if (isa<Target_Type>(value)) { ... }.
///
template <typename Target, typename From>
inline bool isa(const From &Val) {
return isa_wrap<typename std::remove_pointer<Target>::type, From>::call(Val);
}
///
/// \brief Derive cast return type by template parameter From and To.
///
template <typename To, typename From>
struct ReturnTypeDuductionWrap {
typedef To &type;
};
template <typename To, typename From>
struct ReturnTypeDuductionWrap<To, const From> {
typedef const To &type;
};
template <typename To, typename From>
struct ReturnTypeDuductionWrap<To, From *> {
typedef To *type;
};
template <typename To, typename From>
struct ReturnTypeDuductionWrap<To, const From *> {
typedef const To *type;
};
template <typename To, typename From>
struct ReturnTypeDuductionWrap<To, const From *const> {
typedef const To *type;
};
template <typename To, typename From>
struct ReturnTypeDuduction {
typedef typename ReturnTypeDuductionWrap<To, From>::type type;
};
///
/// \brief cast From to To
///
template <typename To, typename From, typename Enable = void>
struct cast_impl {
// This _is_ a simple type, just cast it.
static typename ReturnTypeDuduction<To, From>::type call(const From &Val) {
typename ReturnTypeDuduction<To, From>::type ret =
(typename ReturnTypeDuduction<To, From>::type) const_cast<From &>(Val);
return ret;
}
};
template <typename To, typename From>
inline decltype(auto) cast(const From &Val) {
if (!isa<To>(Val)) {
throw("cast<To>() argument of incompatible type!");
}
return cast_impl<To, const From>::call(Val);
}
template <typename To, typename From>
inline decltype(auto) cast(From &Val) { // NOLINT
if (!isa<To>(Val)) {
throw("cast<To>() argument of incompatible type!");
}
return cast_impl<To, From>::call(Val);
}
template <typename To, typename From>
inline decltype(auto) cast(From *Val) {
if (!isa<To>(Val)) {
throw("cast<To>() argument of incompatible type!");
}
return cast_impl<To, From *>::call(Val);
}
template <typename To, typename From>
inline decltype(auto) cast(std::unique_ptr<From> &&Val) {
if (!isa<To>(Val)) {
throw("cast<To>() argument of incompatible type!");
}
return cast_impl<To, std::unique_ptr<From>>::call(std::move(Val));
}
///
/// \brief dyn_cast From to To.
///
template <typename To, typename From>
inline decltype(auto) dyn_cast(const From &Val) {
return isa<To>(Val) ? cast<To>(Val) : nullptr;
}
template <typename To, typename From>
inline decltype(auto) dyn_cast(From &Val) { // NOLINT
return isa<To>(Val) ? cast<To>(Val) : nullptr;
}
template <typename To, typename From>
inline decltype(auto) dyn_cast(From *Val) {
return isa<To>(Val) ? cast<To>(Val) : nullptr;
}
template <typename To, typename From>
inline decltype(auto) dyn_cast(std::unique_ptr<From> &&Val) {
return isa<To>(Val) ? cast<To>(std::forward<std::unique_ptr<From> &&>(Val))
: nullptr;
}
} // namespace pir