21 #ifndef GTIRB_CASTING_H
22 #define GTIRB_CASTING_H
25 #include <type_traits>
207 template <
typename From>
struct simplify_type {
208 using SimpleType = From;
211 static SimpleType& getSimplifiedValue(From& Val) {
return Val; }
219 template <
typename To,
typename From,
typename Enabler =
void>
struct isa_impl {
220 static inline bool doit(
const From& Val) {
return To::classof(&Val); }
226 template <
typename To,
typename From>
228 To, From, typename
std::enable_if<std::is_base_of<To, From>::value>::type> {
229 static inline bool doit(
const From&) {
return true; }
234 template <
typename To,
typename From>
struct isa_impl_cl {
235 static inline bool doit(
const From& Val) {
236 return isa_impl<To, From>::doit(Val);
242 template <
typename To,
typename From>
struct isa_impl_cl<To, const From> {
243 static inline bool doit(
const From& Val) {
244 return isa_impl<To, From>::doit(Val);
250 template <
typename To,
typename From>
struct isa_impl_cl<To, From*> {
251 static inline bool doit(
const From* Val) {
252 assert(Val &&
"isa<> used on a null pointer");
253 return isa_impl<To, From>::doit(*Val);
259 template <
typename To,
typename From>
struct isa_impl_cl<To, From*
const> {
260 static inline bool doit(
const From* Val) {
261 assert(Val &&
"isa<> used on a null pointer");
262 return isa_impl<To, From>::doit(*Val);
268 template <
typename To,
typename From>
struct isa_impl_cl<To, const From*> {
269 static inline bool doit(
const From* Val) {
270 assert(Val &&
"isa<> used on a null pointer");
271 return isa_impl<To, From>::doit(*Val);
277 template <
typename To,
typename From>
278 struct isa_impl_cl<To, const From*
const> {
279 static inline bool doit(
const From* Val) {
280 assert(Val &&
"isa<> used on a null pointer");
281 return isa_impl<To, From>::doit(*Val);
287 template <
typename To,
typename From,
typename SimpleFrom>
288 struct isa_impl_wrap {
291 static bool doit(
const From& Val) {
292 return isa_impl_wrap<To, SimpleFrom,
293 typename simplify_type<SimpleFrom>::SimpleType>::
294 doit(simplify_type<const From>::getSimplifiedValue(Val));
300 template <
typename To,
typename FromTy>
301 struct isa_impl_wrap<To, FromTy, FromTy> {
303 static bool doit(
const FromTy& Val) {
304 return isa_impl_cl<To, FromTy>::doit(Val);
314 template <
class X,
class Y>[[nodiscard]]
inline bool isa(
const Y& Val) {
315 return isa_impl_wrap<X,
const Y,
316 typename simplify_type<const Y>::SimpleType>::doit(Val);
323 template <
class To,
class From>
struct cast_retty;
329 template <
class To,
class From>
struct cast_retty_impl {
330 using ret_type = To&;
332 template <
class To,
class From>
struct cast_retty_impl<To, const From> {
333 using ret_type =
const To&;
336 template <
class To,
class From>
struct cast_retty_impl<To, From*> {
337 using ret_type = To*;
340 template <
class To,
class From>
struct cast_retty_impl<To, const From*> {
341 using ret_type =
const To*;
344 template <
class To,
class From>
struct cast_retty_impl<To, const From*
const> {
345 using ret_type =
const To*;
350 template <
class To,
class From,
class SimpleFrom>
struct cast_retty_wrap {
354 using ret_type =
typename cast_retty<To, SimpleFrom>::ret_type;
357 template <
class To,
class FromTy>
struct cast_retty_wrap<To, FromTy, FromTy> {
359 using ret_type =
typename cast_retty_impl<To, FromTy>::ret_type;
362 template <
class To,
class From>
struct cast_retty {
363 using ret_type =
typename cast_retty_wrap<
364 To, From,
typename simplify_type<From>::SimpleType>::ret_type;
372 template <
class To,
class From,
class SimpleFrom>
struct cast_convert_val {
374 static typename cast_retty<To, From>::ret_type doit(From& Val) {
375 return cast_convert_val<To, SimpleFrom,
376 typename simplify_type<SimpleFrom>::SimpleType>::
377 doit(simplify_type<From>::getSimplifiedValue(Val));
381 template <
class To,
class FromTy>
struct cast_convert_val<To, FromTy, FromTy> {
383 static typename cast_retty<To, FromTy>::ret_type doit(
const FromTy& Val) {
384 typename cast_retty<To, FromTy>::ret_type Res2 =
385 (
typename cast_retty<To, FromTy>::ret_type)
const_cast<FromTy&
>(Val);
392 template <
class X>
struct is_simple_type {
393 static const bool value =
394 std::is_same<X, typename simplify_type<X>::SimpleType>::value;
405 template <
class X,
class Y>
406 inline typename std::enable_if<!is_simple_type<Y>::value,
407 typename cast_retty<X, const Y>::ret_type>::type
409 assert(isa<X>(Val) &&
"cast<Ty>() argument of incompatible type!");
410 return cast_convert_val<
411 X,
const Y,
typename simplify_type<const Y>::SimpleType>::doit(Val);
414 template <
class X,
class Y>
415 inline typename cast_retty<X, Y>::ret_type
cast(Y& Val) {
416 assert(isa<X>(Val) &&
"cast<Ty>() argument of incompatible type!");
417 return cast_convert_val<X, Y, typename simplify_type<Y>::SimpleType>::doit(
421 template <
class X,
class Y>
422 inline typename cast_retty<X, Y*>::ret_type
cast(Y* Val) {
423 assert(isa<X>(Val) &&
"cast<Ty>() argument of incompatible type!");
424 return cast_convert_val<X, Y*, typename simplify_type<Y*>::SimpleType>::doit(
431 template <
class X,
class Y>
433 typename std::enable_if<!is_simple_type<Y>::value,
434 typename cast_retty<X, const Y>::ret_type>::type
438 assert(isa<X>(Val) &&
"cast_or_null<Ty>() argument of incompatible type!");
442 template <
class X,
class Y>
444 typename std::enable_if<!is_simple_type<Y>::value,
445 typename cast_retty<X, Y>::ret_type>::type
449 assert(isa<X>(Val) &&
"cast_or_null<Ty>() argument of incompatible type!");
453 template <
class X,
class Y>
454 [[nodiscard]]
inline typename cast_retty<X, Y*>::ret_type
cast_or_null(Y* Val) {
457 assert(isa<X>(Val) &&
"cast_or_null<Ty>() argument of incompatible type!");
469 template <
class X,
class Y>
471 typename std::enable_if<!is_simple_type<Y>::value,
472 typename cast_retty<X, const Y>::ret_type>::type
474 return isa<X>(Val) ? cast<X>(Val) :
nullptr;
477 template <
class X,
class Y>
478 [[nodiscard]]
inline typename cast_retty<X, Y>::ret_type
dyn_cast(Y& Val) {
479 return isa<X>(Val) ? cast<X>(Val) :
nullptr;
482 template <
class X,
class Y>
483 [[nodiscard]]
inline typename cast_retty<X, Y*>::ret_type
dyn_cast(Y* Val) {
484 return isa<X>(Val) ? cast<X>(Val) :
nullptr;
490 template <
class X,
class Y>
492 typename std::enable_if<!is_simple_type<Y>::value,
493 typename cast_retty<X, const Y>::ret_type>::type
495 return (Val && isa<X>(Val)) ? cast<X>(Val) :
nullptr;
498 template <
class X,
class Y>
500 typename std::enable_if<!is_simple_type<Y>::value,
501 typename cast_retty<X, Y>::ret_type>::type
503 return (Val && isa<X>(Val)) ? cast<X>(Val) :
nullptr;
506 template <
class X,
class Y>
507 [[nodiscard]]
inline typename cast_retty<X, Y*>::ret_type
509 return (Val && isa<X>(Val)) ? cast<X>(Val) :
nullptr;
512 #endif // GTIRB_CASTING_H