File indexing completed on 2026-05-10 08:44:28
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_SUPPORT_CASTING_H
0015 #define LLVM_SUPPORT_CASTING_H
0016
0017 #include "llvm/Support/Compiler.h"
0018 #include "llvm/Support/type_traits.h"
0019 #include <cassert>
0020 #include <memory>
0021 #include <optional>
0022 #include <type_traits>
0023
0024 namespace llvm {
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 template <typename From> struct simplify_type {
0035 using SimpleType = From;
0036
0037
0038 static SimpleType &getSimplifiedValue(From &Val) { return Val; }
0039 };
0040
0041 template <typename From> struct simplify_type<const From> {
0042 using NonConstSimpleType = typename simplify_type<From>::SimpleType;
0043 using SimpleType = typename add_const_past_pointer<NonConstSimpleType>::type;
0044 using RetType =
0045 typename add_lvalue_reference_if_not_pointer<SimpleType>::type;
0046
0047 static RetType getSimplifiedValue(const From &Val) {
0048 return simplify_type<From>::getSimplifiedValue(const_cast<From &>(Val));
0049 }
0050 };
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063 template <typename To, typename From, typename Enabler = void> struct isa_impl {
0064 static inline bool doit(const From &Val) { return To::classof(&Val); }
0065 };
0066
0067
0068 template <typename To, typename From>
0069 struct isa_impl<To, From, std::enable_if_t<std::is_base_of_v<To, From>>> {
0070 static inline bool doit(const From &) { return true; }
0071 };
0072
0073 template <typename To, typename From> struct isa_impl_cl {
0074 static inline bool doit(const From &Val) {
0075 return isa_impl<To, From>::doit(Val);
0076 }
0077 };
0078
0079 template <typename To, typename From> struct isa_impl_cl<To, const From> {
0080 static inline bool doit(const From &Val) {
0081 return isa_impl<To, From>::doit(Val);
0082 }
0083 };
0084
0085 template <typename To, typename From>
0086 struct isa_impl_cl<To, const std::unique_ptr<From>> {
0087 static inline bool doit(const std::unique_ptr<From> &Val) {
0088 assert(Val && "isa<> used on a null pointer");
0089 return isa_impl_cl<To, From>::doit(*Val);
0090 }
0091 };
0092
0093 template <typename To, typename From> struct isa_impl_cl<To, From *> {
0094 static inline bool doit(const From *Val) {
0095 assert(Val && "isa<> used on a null pointer");
0096 return isa_impl<To, From>::doit(*Val);
0097 }
0098 };
0099
0100 template <typename To, typename From> struct isa_impl_cl<To, From *const> {
0101 static inline bool doit(const From *Val) {
0102 assert(Val && "isa<> used on a null pointer");
0103 return isa_impl<To, From>::doit(*Val);
0104 }
0105 };
0106
0107 template <typename To, typename From> struct isa_impl_cl<To, const From *> {
0108 static inline bool doit(const From *Val) {
0109 assert(Val && "isa<> used on a null pointer");
0110 return isa_impl<To, From>::doit(*Val);
0111 }
0112 };
0113
0114 template <typename To, typename From>
0115 struct isa_impl_cl<To, const From *const> {
0116 static inline bool doit(const From *Val) {
0117 assert(Val && "isa<> used on a null pointer");
0118 return isa_impl<To, From>::doit(*Val);
0119 }
0120 };
0121
0122 template <typename To, typename From, typename SimpleFrom>
0123 struct isa_impl_wrap {
0124
0125
0126 static bool doit(const From &Val) {
0127 return isa_impl_wrap<To, SimpleFrom,
0128 typename simplify_type<SimpleFrom>::SimpleType>::
0129 doit(simplify_type<const From>::getSimplifiedValue(Val));
0130 }
0131 };
0132
0133 template <typename To, typename FromTy>
0134 struct isa_impl_wrap<To, FromTy, FromTy> {
0135
0136 static bool doit(const FromTy &Val) {
0137 return isa_impl_cl<To, FromTy>::doit(Val);
0138 }
0139 };
0140
0141
0142
0143
0144
0145 template <class To, class From> struct cast_retty;
0146
0147
0148
0149 template <class To, class From> struct cast_retty_impl {
0150 using ret_type = To &;
0151 };
0152 template <class To, class From> struct cast_retty_impl<To, const From> {
0153 using ret_type = const To &;
0154 };
0155
0156 template <class To, class From> struct cast_retty_impl<To, From *> {
0157 using ret_type = To *;
0158 };
0159
0160 template <class To, class From> struct cast_retty_impl<To, const From *> {
0161 using ret_type = const To *;
0162 };
0163
0164 template <class To, class From> struct cast_retty_impl<To, const From *const> {
0165 using ret_type = const To *;
0166 };
0167
0168 template <class To, class From>
0169 struct cast_retty_impl<To, std::unique_ptr<From>> {
0170 private:
0171 using PointerType = typename cast_retty_impl<To, From *>::ret_type;
0172 using ResultType = std::remove_pointer_t<PointerType>;
0173
0174 public:
0175 using ret_type = std::unique_ptr<ResultType>;
0176 };
0177
0178 template <class To, class From, class SimpleFrom> struct cast_retty_wrap {
0179
0180
0181
0182 using ret_type = typename cast_retty<To, SimpleFrom>::ret_type;
0183 };
0184
0185 template <class To, class FromTy> struct cast_retty_wrap<To, FromTy, FromTy> {
0186
0187 using ret_type = typename cast_retty_impl<To, FromTy>::ret_type;
0188 };
0189
0190 template <class To, class From> struct cast_retty {
0191 using ret_type = typename cast_retty_wrap<
0192 To, From, typename simplify_type<From>::SimpleType>::ret_type;
0193 };
0194
0195
0196
0197
0198
0199
0200
0201
0202 template <class To, class From, class SimpleFrom> struct cast_convert_val {
0203
0204 static typename cast_retty<To, From>::ret_type doit(const From &Val) {
0205 return cast_convert_val<To, SimpleFrom,
0206 typename simplify_type<SimpleFrom>::SimpleType>::
0207 doit(simplify_type<From>::getSimplifiedValue(const_cast<From &>(Val)));
0208 }
0209 };
0210
0211 template <class To, class FromTy> struct cast_convert_val<To, FromTy, FromTy> {
0212
0213 static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) {
0214 return *(std::remove_reference_t<typename cast_retty<To, FromTy>::ret_type>
0215 *)&const_cast<FromTy &>(Val);
0216 }
0217 };
0218
0219 template <class To, class FromTy>
0220 struct cast_convert_val<To, FromTy *, FromTy *> {
0221
0222 static typename cast_retty<To, FromTy *>::ret_type doit(const FromTy *Val) {
0223 return (typename cast_retty<To, FromTy *>::ret_type) const_cast<FromTy *>(
0224 Val);
0225 }
0226 };
0227
0228
0229
0230
0231
0232 template <class X> struct is_simple_type {
0233 static const bool value =
0234 std::is_same_v<X, typename simplify_type<X>::SimpleType>;
0235 };
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252 template <typename To, typename From, typename Enable = void>
0253 struct CastIsPossible {
0254 static inline bool isPossible(const From &f) {
0255 return isa_impl_wrap<
0256 To, const From,
0257 typename simplify_type<const From>::SimpleType>::doit(f);
0258 }
0259 };
0260
0261
0262
0263
0264
0265 template <typename To, typename From>
0266 struct CastIsPossible<To, std::optional<From>> {
0267 static inline bool isPossible(const std::optional<From> &f) {
0268 assert(f && "CastIsPossible::isPossible called on a nullopt!");
0269 return isa_impl_wrap<
0270 To, const From,
0271 typename simplify_type<const From>::SimpleType>::doit(*f);
0272 }
0273 };
0274
0275
0276
0277 template <typename To, typename From>
0278 struct CastIsPossible<To, From, std::enable_if_t<std::is_base_of_v<To, From>>> {
0279 static inline bool isPossible(const From &f) { return true; }
0280 };
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301 template <typename To> struct NullableValueCastFailed {
0302 static To castFailed() { return To(nullptr); }
0303 };
0304
0305
0306
0307
0308 template <typename To, typename From, typename Derived>
0309 struct DefaultDoCastIfPossible {
0310 static To doCastIfPossible(From f) {
0311 if (!Derived::isPossible(f))
0312 return Derived::castFailed();
0313 return Derived::doCast(f);
0314 }
0315 };
0316
0317 namespace detail {
0318
0319
0320 template <typename OptionalDerived, typename Default>
0321 using SelfType = std::conditional_t<std::is_same_v<OptionalDerived, void>,
0322 Default, OptionalDerived>;
0323 }
0324
0325
0326
0327
0328 template <typename To, typename From, typename Derived = void>
0329 struct ValueFromPointerCast
0330 : public CastIsPossible<To, From *>,
0331 public NullableValueCastFailed<To>,
0332 public DefaultDoCastIfPossible<
0333 To, From *,
0334 detail::SelfType<Derived, ValueFromPointerCast<To, From>>> {
0335 static inline To doCast(From *f) { return To(f); }
0336 };
0337
0338
0339
0340
0341
0342 template <typename To, typename From, typename Derived = void>
0343 struct UniquePtrCast : public CastIsPossible<To, From *> {
0344 using Self = detail::SelfType<Derived, UniquePtrCast<To, From>>;
0345 using CastResultType = std::unique_ptr<
0346 std::remove_reference_t<typename cast_retty<To, From>::ret_type>>;
0347
0348 static inline CastResultType doCast(std::unique_ptr<From> &&f) {
0349 return CastResultType((typename CastResultType::element_type *)f.release());
0350 }
0351
0352 static inline CastResultType castFailed() { return CastResultType(nullptr); }
0353
0354 static inline CastResultType doCastIfPossible(std::unique_ptr<From> &f) {
0355 if (!Self::isPossible(f.get()))
0356 return castFailed();
0357 return doCast(std::move(f));
0358 }
0359 };
0360
0361
0362
0363
0364 template <typename To, typename From, typename Derived = void>
0365 struct OptionalValueCast
0366 : public CastIsPossible<To, From>,
0367 public DefaultDoCastIfPossible<
0368 std::optional<To>, From,
0369 detail::SelfType<Derived, OptionalValueCast<To, From>>> {
0370 static inline std::optional<To> castFailed() { return std::optional<To>{}; }
0371
0372 static inline std::optional<To> doCast(const From &f) { return To(f); }
0373 };
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387 template <typename To, typename From, typename ForwardTo>
0388 struct ConstStrippingForwardingCast {
0389
0390 using DecayedFrom = std::remove_cv_t<std::remove_pointer_t<From>>;
0391
0392 using NonConstFrom =
0393 std::conditional_t<std::is_pointer_v<From>, DecayedFrom *, DecayedFrom &>;
0394
0395 static inline bool isPossible(const From &f) {
0396 return ForwardTo::isPossible(const_cast<NonConstFrom>(f));
0397 }
0398
0399 static inline decltype(auto) castFailed() { return ForwardTo::castFailed(); }
0400
0401 static inline decltype(auto) doCast(const From &f) {
0402 return ForwardTo::doCast(const_cast<NonConstFrom>(f));
0403 }
0404
0405 static inline decltype(auto) doCastIfPossible(const From &f) {
0406 return ForwardTo::doCastIfPossible(const_cast<NonConstFrom>(f));
0407 }
0408 };
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422 template <typename To, typename From, typename ForwardTo>
0423 struct ForwardToPointerCast {
0424 static inline bool isPossible(const From &f) {
0425 return ForwardTo::isPossible(&f);
0426 }
0427
0428 static inline decltype(auto) doCast(const From &f) {
0429 return *ForwardTo::doCast(&f);
0430 }
0431 };
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475 template <typename To, typename From, typename Enable = void>
0476 struct CastInfo : public CastIsPossible<To, From> {
0477 using Self = CastInfo<To, From, Enable>;
0478
0479 using CastReturnType = typename cast_retty<To, From>::ret_type;
0480
0481 static inline CastReturnType doCast(const From &f) {
0482 return cast_convert_val<
0483 To, From,
0484 typename simplify_type<From>::SimpleType>::doit(const_cast<From &>(f));
0485 }
0486
0487
0488
0489
0490 static inline CastReturnType castFailed() { return CastReturnType(nullptr); }
0491
0492 static inline CastReturnType doCastIfPossible(const From &f) {
0493 if (!Self::isPossible(f))
0494 return castFailed();
0495 return doCast(f);
0496 }
0497 };
0498
0499
0500
0501
0502 template <typename To, typename From>
0503 struct CastInfo<To, From, std::enable_if_t<!is_simple_type<From>::value>> {
0504 using Self = CastInfo<To, From>;
0505 using SimpleFrom = typename simplify_type<From>::SimpleType;
0506 using SimplifiedSelf = CastInfo<To, SimpleFrom>;
0507
0508 static inline bool isPossible(From &f) {
0509 return SimplifiedSelf::isPossible(
0510 simplify_type<From>::getSimplifiedValue(f));
0511 }
0512
0513 static inline decltype(auto) doCast(From &f) {
0514 return SimplifiedSelf::doCast(simplify_type<From>::getSimplifiedValue(f));
0515 }
0516
0517 static inline decltype(auto) castFailed() {
0518 return SimplifiedSelf::castFailed();
0519 }
0520
0521 static inline decltype(auto) doCastIfPossible(From &f) {
0522 return SimplifiedSelf::doCastIfPossible(
0523 simplify_type<From>::getSimplifiedValue(f));
0524 }
0525 };
0526
0527
0528
0529
0530
0531
0532 template <typename To, typename From>
0533 struct CastInfo<To, std::unique_ptr<From>> : public UniquePtrCast<To, From> {};
0534
0535
0536
0537
0538 template <typename To, typename From>
0539 struct CastInfo<To, std::optional<From>> : public OptionalValueCast<To, From> {
0540 };
0541
0542
0543
0544
0545
0546
0547 template <typename To, typename From>
0548 [[nodiscard]] inline bool isa(const From &Val) {
0549 return CastInfo<To, const From>::isPossible(Val);
0550 }
0551
0552 template <typename First, typename Second, typename... Rest, typename From>
0553 [[nodiscard]] inline bool isa(const From &Val) {
0554 return isa<First>(Val) || isa<Second, Rest...>(Val);
0555 }
0556
0557
0558
0559
0560
0561
0562
0563
0564 template <typename To, typename From>
0565 [[nodiscard]] inline decltype(auto) cast(const From &Val) {
0566 assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
0567 return CastInfo<To, const From>::doCast(Val);
0568 }
0569
0570 template <typename To, typename From>
0571 [[nodiscard]] inline decltype(auto) cast(From &Val) {
0572 assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
0573 return CastInfo<To, From>::doCast(Val);
0574 }
0575
0576 template <typename To, typename From>
0577 [[nodiscard]] inline decltype(auto) cast(From *Val) {
0578 assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
0579 return CastInfo<To, From *>::doCast(Val);
0580 }
0581
0582 template <typename To, typename From>
0583 [[nodiscard]] inline decltype(auto) cast(std::unique_ptr<From> &&Val) {
0584 assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
0585 return CastInfo<To, std::unique_ptr<From>>::doCast(std::move(Val));
0586 }
0587
0588
0589
0590
0591
0592 template <typename T>
0593 constexpr bool IsNullable =
0594 std::is_pointer_v<T> || std::is_constructible_v<T, std::nullptr_t>;
0595
0596
0597
0598
0599
0600
0601
0602 template <typename T, typename Enable = void> struct ValueIsPresent {
0603 using UnwrappedType = T;
0604 static inline bool isPresent(const T &t) { return true; }
0605 static inline decltype(auto) unwrapValue(T &t) { return t; }
0606 };
0607
0608
0609 template <typename T> struct ValueIsPresent<std::optional<T>> {
0610 using UnwrappedType = T;
0611 static inline bool isPresent(const std::optional<T> &t) {
0612 return t.has_value();
0613 }
0614 static inline decltype(auto) unwrapValue(std::optional<T> &t) { return *t; }
0615 };
0616
0617
0618
0619 template <typename T>
0620 struct ValueIsPresent<T, std::enable_if_t<IsNullable<T>>> {
0621 using UnwrappedType = T;
0622 static inline bool isPresent(const T &t) { return t != T(nullptr); }
0623 static inline decltype(auto) unwrapValue(T &t) { return t; }
0624 };
0625
0626 namespace detail {
0627
0628
0629 template <typename T> inline bool isPresent(const T &t) {
0630 return ValueIsPresent<typename simplify_type<T>::SimpleType>::isPresent(
0631 simplify_type<T>::getSimplifiedValue(const_cast<T &>(t)));
0632 }
0633
0634
0635 template <typename T> inline decltype(auto) unwrapValue(T &t) {
0636 return ValueIsPresent<T>::unwrapValue(t);
0637 }
0638 }
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648 template <typename To, typename From>
0649 [[nodiscard]] inline decltype(auto) dyn_cast(const From &Val) {
0650 assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
0651 return CastInfo<To, const From>::doCastIfPossible(Val);
0652 }
0653
0654 template <typename To, typename From>
0655 [[nodiscard]] inline decltype(auto) dyn_cast(From &Val) {
0656 assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
0657 return CastInfo<To, From>::doCastIfPossible(Val);
0658 }
0659
0660 template <typename To, typename From>
0661 [[nodiscard]] inline decltype(auto) dyn_cast(From *Val) {
0662 assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
0663 return CastInfo<To, From *>::doCastIfPossible(Val);
0664 }
0665
0666 template <typename To, typename From>
0667 [[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &Val) {
0668 assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
0669 return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible(Val);
0670 }
0671
0672
0673
0674 template <typename... X, class Y>
0675 [[nodiscard]] inline bool isa_and_present(const Y &Val) {
0676 if (!detail::isPresent(Val))
0677 return false;
0678 return isa<X...>(Val);
0679 }
0680
0681 template <typename... X, class Y>
0682 [[nodiscard]] inline bool isa_and_nonnull(const Y &Val) {
0683 return isa_and_present<X...>(Val);
0684 }
0685
0686
0687
0688 template <class X, class Y>
0689 [[nodiscard]] inline auto cast_if_present(const Y &Val) {
0690 if (!detail::isPresent(Val))
0691 return CastInfo<X, const Y>::castFailed();
0692 assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!");
0693 return cast<X>(detail::unwrapValue(Val));
0694 }
0695
0696 template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y &Val) {
0697 if (!detail::isPresent(Val))
0698 return CastInfo<X, Y>::castFailed();
0699 assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!");
0700 return cast<X>(detail::unwrapValue(Val));
0701 }
0702
0703 template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y *Val) {
0704 if (!detail::isPresent(Val))
0705 return CastInfo<X, Y *>::castFailed();
0706 assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!");
0707 return cast<X>(detail::unwrapValue(Val));
0708 }
0709
0710 template <class X, class Y>
0711 [[nodiscard]] inline auto cast_if_present(std::unique_ptr<Y> &&Val) {
0712 if (!detail::isPresent(Val))
0713 return UniquePtrCast<X, Y>::castFailed();
0714 return UniquePtrCast<X, Y>::doCast(std::move(Val));
0715 }
0716
0717
0718
0719
0720 template <class X, class Y> auto cast_or_null(const Y &Val) {
0721 return cast_if_present<X>(Val);
0722 }
0723
0724 template <class X, class Y> auto cast_or_null(Y &Val) {
0725 return cast_if_present<X>(Val);
0726 }
0727
0728 template <class X, class Y> auto cast_or_null(Y *Val) {
0729 return cast_if_present<X>(Val);
0730 }
0731
0732 template <class X, class Y> auto cast_or_null(std::unique_ptr<Y> &&Val) {
0733 return cast_if_present<X>(std::move(Val));
0734 }
0735
0736
0737
0738 template <class X, class Y> auto dyn_cast_if_present(const Y &Val) {
0739 if (!detail::isPresent(Val))
0740 return CastInfo<X, const Y>::castFailed();
0741 return CastInfo<X, const Y>::doCastIfPossible(detail::unwrapValue(Val));
0742 }
0743
0744 template <class X, class Y> auto dyn_cast_if_present(Y &Val) {
0745 if (!detail::isPresent(Val))
0746 return CastInfo<X, Y>::castFailed();
0747 return CastInfo<X, Y>::doCastIfPossible(detail::unwrapValue(Val));
0748 }
0749
0750 template <class X, class Y> auto dyn_cast_if_present(Y *Val) {
0751 if (!detail::isPresent(Val))
0752 return CastInfo<X, Y *>::castFailed();
0753 return CastInfo<X, Y *>::doCastIfPossible(detail::unwrapValue(Val));
0754 }
0755
0756
0757
0758
0759 template <class X, class Y> auto dyn_cast_or_null(const Y &Val) {
0760 return dyn_cast_if_present<X>(Val);
0761 }
0762
0763 template <class X, class Y> auto dyn_cast_or_null(Y &Val) {
0764 return dyn_cast_if_present<X>(Val);
0765 }
0766
0767 template <class X, class Y> auto dyn_cast_or_null(Y *Val) {
0768 return dyn_cast_if_present<X>(Val);
0769 }
0770
0771
0772
0773
0774
0775
0776 template <class X, class Y>
0777 [[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType
0778 unique_dyn_cast(std::unique_ptr<Y> &Val) {
0779 if (!isa<X>(Val))
0780 return nullptr;
0781 return cast<X>(std::move(Val));
0782 }
0783
0784 template <class X, class Y>
0785 [[nodiscard]] inline auto unique_dyn_cast(std::unique_ptr<Y> &&Val) {
0786 return unique_dyn_cast<X, Y>(Val);
0787 }
0788
0789
0790
0791 template <class X, class Y>
0792 [[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType
0793 unique_dyn_cast_or_null(std::unique_ptr<Y> &Val) {
0794 if (!Val)
0795 return nullptr;
0796 return unique_dyn_cast<X, Y>(Val);
0797 }
0798
0799 template <class X, class Y>
0800 [[nodiscard]] inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &&Val) {
0801 return unique_dyn_cast_or_null<X, Y>(Val);
0802 }
0803
0804
0805
0806
0807
0808
0809
0810
0811
0812
0813 namespace detail {
0814 template <typename... Types> struct IsaCheckPredicate {
0815 template <typename T> [[nodiscard]] bool operator()(const T &Val) const {
0816 return isa<Types...>(Val);
0817 }
0818 };
0819
0820 template <typename... Types> struct IsaAndPresentCheckPredicate {
0821 template <typename T> [[nodiscard]] bool operator()(const T &Val) const {
0822 return isa_and_present<Types...>(Val);
0823 }
0824 };
0825 }
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835 template <typename... Types>
0836 inline constexpr detail::IsaCheckPredicate<Types...> IsaPred{};
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846 template <typename... Types>
0847 inline constexpr detail::IsaAndPresentCheckPredicate<Types...>
0848 IsaAndPresentPred{};
0849
0850 }
0851
0852 #endif