14 #if defined(XRTRAITS_HAVE_EXCEPTIONS) && defined(XRTRAITS_HAVE_CONSTEXPR_IF) 20 #define XRTRAITS_HAVE_DYNAMIC_VERIFIED 33 #include <openxr/openxr.h> 38 #ifdef XRTRAITS_DOXYGEN 44 #define XRTRAITS_DYNAMIC_VERIFIED_ALWAYS_RECHECK 45 #endif // XRTRAITS_DOXYGEN 47 #ifdef XRTRAITS_DYNAMIC_VERIFIED_ALWAYS_RECHECK 53 #define XRTRAITS_NOEXCEPT_IF_NOT_RECHECKING 55 #define XRTRAITS_NOEXCEPT_IF_NOT_RECHECKING noexcept 86 template <
typename T>
class DynamicVerifiedOrNull;
121 template <
typename T>
class DynamicVerified;
142 template <
typename T>
144 T*
const& param,
const char* paramName =
nullptr,
145 XrResult errorCode = exceptions::DEFAULT_TYPE_ERROR_CODE);
167 template <
typename T>
169 verifyDynamicType(T* param,
const char* paramName =
nullptr,
170 XrResult errorCode = exceptions::DEFAULT_TYPE_ERROR_CODE);
191 template <
typename T>
193 verifyDynamicType(T& param,
const char* paramName =
nullptr,
194 XrResult errorCode = exceptions::DEFAULT_TYPE_ERROR_CODE);
217 template <
typename T,
typename U>
219 U*
const& param,
const char* paramName =
nullptr,
220 XrResult errorCode = exceptions::DEFAULT_TYPE_ERROR_CODE);
243 template <
typename T,
typename U>
245 U& param,
const char* paramName =
nullptr,
246 XrResult errorCode = exceptions::DEFAULT_TYPE_ERROR_CODE);
266 template <
typename T,
typename U>
268 required_verified_or_null_cast(
269 U* param,
const char* paramName =
nullptr,
270 XrResult errorCode = exceptions::DEFAULT_TYPE_ERROR_CODE);
287 template <
typename T>
289 ensureNotNull(DynamicVerifiedOrNull<T>
const& param,
290 const char* paramName =
nullptr,
291 XrResult errorCode = exceptions::DEFAULT_TYPE_ERROR_CODE);
310 template <
typename TargetType,
typename SourceType>
312 getFromChain(SourceType* param,
const char* paramName =
nullptr,
313 XrResult errorCode = exceptions::DEFAULT_TYPE_ERROR_CODE);
332 template <
typename TargetType,
typename SourceType>
334 traits::is_xr_tagged_type_v<SourceType>, DynamicVerified<TargetType>>
335 getFromChain(SourceType& param,
const char* paramName =
nullptr,
336 XrResult errorCode = exceptions::DEFAULT_TYPE_ERROR_CODE);
355 template <
typename TargetType,
typename SourceType>
357 getFromChain(DynamicVerified<SourceType>
const& param,
358 const char* paramName =
nullptr,
359 XrResult errorCode = exceptions::DEFAULT_TYPE_ERROR_CODE);
377 template <
typename TargetType,
typename SourceType>
379 tryGetFromChain(SourceType* param) noexcept;
393 template <
typename TargetType,
typename SourceType>
395 traits::is_xr_tagged_type_v<SourceType>, DynamicVerifiedOrNull<TargetType>>
396 tryGetFromChain(SourceType& param) noexcept;
410 template <
typename TargetType,
typename SourceType>
412 tryGetFromChain(DynamicVerifiedOrNull<SourceType>
const& param) noexcept;
421 #define XRTRAITS_VERIFY_DYNAMIC_TYPE(PARAM) \ 422 ::xrtraits::verifyDynamicType(PARAM, #PARAM) 430 #define XRTRAITS_VERIFY_DYNAMIC_TYPE_OR_NULL(PARAM) \ 431 ::xrtraits::verifyDynamicTypeOrNull(PARAM, #PARAM) 438 template <
typename T>
class DynamicVerifiedSpan;
443 template <
typename T>
445 make_dynamic_verified_span(
446 T* pointer, std::ptrdiff_t size,
const char* paramName =
nullptr,
447 XrResult errorCode = exceptions::DEFAULT_TYPE_ERROR_CODE);
457 #define XRTRAITS_MAKE_POLYMORPHIC_SPAN(PARAM, SIZE) \ 458 ::xrtraits::make_polymorphic_span(PARAM, SIZE, #PARAM) 466 #define XRTRAITS_MAKE_DYNAMIC_VERIFIED_SPAN(PARAM, SIZE) \ 467 ::xrtraits::make_dynamic_verified_span(PARAM, SIZE, #PARAM) 470 #ifndef XRTRAITS_DOXYGEN 475 struct GetFromChain_t
477 constexpr
explicit GetFromChain_t() =
default;
483 constexpr GetFromChain_t get_from_chain{};
488 template <
typename T,
typename U>
489 inline constexpr T& getFromChainImpl(U* param,
const char* paramName,
493 traits::is_xr_tagged_type_v<U>,
494 "Can only use getFromChain() on types known to have type " 495 "and next members.");
497 if (
nullptr == param) {
498 throw exceptions::get_from_chain_error(
499 paramName,
nullptr, traits::xr_type_tag_v<T>,
502 auto* typed = casts::xr_get_chained_struct<T*>(param);
503 if (
nullptr == typed) {
504 throw exceptions::get_from_chain_error(
505 paramName, param->type, traits::xr_type_tag_v<T>,
513 template <
typename T,
typename U>
514 inline constexpr T* tryGetFromChainImpl(U* param) noexcept
516 static_assert(traits::is_xr_tagged_type_v<U>,
517 "Can only use tryGetFromChain() on types known " 518 "to have type and next members.");
521 "Type parameter to tryGetFromChain() should just be the " 522 "structure type, not a pointer type.");
525 "Type parameter to tryGetFromChain() should just be the " 526 "structure type, not a reference type.");
528 if (
nullptr == param) {
532 auto* typed = casts::xr_get_chained_struct<T*>(param);
538 #endif // !XRTRAITS_DOXYGEN 540 template <
typename T>
class DynamicVerifiedOrNull
544 traits::has_xr_type_tag_v<T>,
545 "Can only use verifyDynamicTypeOrNull and DynamicVerifiedOrNull on " 546 "types with an associated XrStructureType enum value.");
556 constexpr DynamicVerifiedOrNull(T* param,
const char* paramName,
560 if ((wrapped_ !=
nullptr) &&
561 (wrapped_->type != traits::xr_type_tag_v<T>)) {
562 throw exceptions::type_error(paramName, wrapped_->type,
563 traits::xr_type_tag_v<T>,
576 constexpr DynamicVerifiedOrNull(T& param,
const char* paramName,
578 : DynamicVerifiedOrNull(std::addressof(param), paramName, errorCode)
586 constexpr DynamicVerifiedOrNull(std::nullptr_t ) noexcept
596 template <
typename U>
597 constexpr DynamicVerifiedOrNull(
598 U* param, detail::GetFromChain_t
const& ) noexcept
599 : DynamicVerifiedOrNull(detail::tryGetFromChainImpl<T>(param))
603 constexpr DynamicVerifiedOrNull(DynamicVerifiedOrNull
const&) noexcept =
607 constexpr DynamicVerifiedOrNull&
608 operator=(DynamicVerifiedOrNull
const&) noexcept =
default;
611 constexpr DynamicVerifiedOrNull(DynamicVerifiedOrNull&& other) noexcept
612 : DynamicVerifiedOrNull(
nullptr)
614 std::swap(wrapped_, other.wrapped_);
618 constexpr DynamicVerifiedOrNull&
619 operator=(DynamicVerifiedOrNull&& other) noexcept
622 std::swap(wrapped_, other.wrapped_);
627 ~DynamicVerifiedOrNull() =
default;
640 template <
typename U>
641 DynamicVerifiedOrNull(DynamicVerifiedOrNull<U>
const&) =
delete;
644 constexpr
bool valid()
const {
return wrapped_ !=
nullptr; }
647 constexpr T*
get()
const 650 throw exceptions::xr_logic_error(
651 "Used a DynamicVerifiedOrNull without checking to " 652 "see if it was null");
654 #ifdef XRTRAITS_DYNAMIC_VERIFIED_ALWAYS_RECHECK 655 if (wrapped_->type != traits::xr_type_tag_v<T>) {
656 throw exceptions::xr_logic_error(
657 "Something changed the .type member of an OpenXR " 658 "struct after a DynamicVerifiedOrNull wrapper was " 661 #endif // XRTRAITS_DYNAMIC_VERIFIED_ALWAYS_RECHECK 668 constexpr T* operator->()
const {
return get(); }
673 constexpr T& operator*()
const {
return *
get(); }
678 T* uncheckedGet() const noexcept {
return wrapped_; }
685 explicit constexpr DynamicVerifiedOrNull(T* wrapped) noexcept
689 (wrapped->type == traits::xr_type_tag_v<T>));
701 template <
typename T>
702 inline constexpr
bool operator==(DynamicVerifiedOrNull<T>
const& wrapper,
705 return !wrapper.valid();
712 template <
typename T>
713 inline constexpr
bool operator==(std::nullptr_t ,
714 DynamicVerifiedOrNull<T>
const& wrapper)
716 return !wrapper.valid();
723 template <
typename T>
724 inline constexpr
bool operator!=(DynamicVerifiedOrNull<T>
const& wrapper,
727 return wrapper.valid();
734 template <
typename T>
735 inline constexpr
bool operator!=(std::nullptr_t ,
736 DynamicVerifiedOrNull<T>
const& wrapper)
738 return wrapper.valid();
741 template <
typename T>
class DynamicVerified :
public DynamicVerifiedOrNull<T>
743 using Base = DynamicVerifiedOrNull<T>;
746 static_assert(traits::has_xr_type_tag_v<T>,
747 "Can only use verifyDynamicType and DynamicVerified on " 748 "types with an associated XrStructureType enum value.");
749 static_assert(!is_pointer_v<T>,
750 "Can't specify a pointer type as the type parameter to " 752 static_assert(!is_reference_v<T>,
753 "Can't specify a pointer type as the type parameter to " 764 constexpr DynamicVerified(T& wrapped,
const char* paramName,
766 : DynamicVerifiedOrNull<T>(std::addressof(wrapped), paramName,
776 template <
typename U>
777 constexpr DynamicVerified(U* param,
const char* paramName,
779 detail::GetFromChain_t
const& )
781 detail::getFromChainImpl<T>(param, paramName, errorCode))
797 template <
typename U>
798 DynamicVerified(DynamicVerified<U>
const&) =
delete;
801 constexpr DynamicVerified(DynamicVerified
const&) noexcept =
default;
804 constexpr DynamicVerified&
805 operator=(DynamicVerified
const&) noexcept =
default;
808 constexpr DynamicVerified(DynamicVerified&&) noexcept = default;
811 constexpr DynamicVerified&
812 operator=(DynamicVerified&&) noexcept = default;
815 ~DynamicVerified() = default;
818 DynamicVerified(std::nullptr_t) = delete;
821 constexpr T* get() const XRTRAITS_NOEXCEPT_IF_NOT_RECHECKING
823 #ifdef XRTRAITS_DYNAMIC_VERIFIED_ALWAYS_RECHECK 824 if (Base::uncheckedGet()->type != traits::xr_type_tag_v<T>) {
825 throw exceptions::xr_logic_error(
826 "Something changed the .type member of an OpenXR " 827 "struct after a DynamicVerified wrapper was " 832 traits::xr_type_tag_v<T>);
833 #endif // XRTRAITS_DYNAMIC_VERIFIED_ALWAYS_RECHECK 834 return Base::uncheckedGet();
840 constexpr T* operator->() const XRTRAITS_NOEXCEPT_IF_NOT_RECHECKING
848 constexpr T& operator*() const XRTRAITS_NOEXCEPT_IF_NOT_RECHECKING
856 template <
typename U>
friend struct Initialized;
863 explicit constexpr DynamicVerified(T& wrapped) noexcept
864 : DynamicVerifiedOrNull<T>(std::addressof(wrapped))
866 GSL_ASSUME(wrapped.type == traits::xr_type_tag_v<T>);
875 template <
typename T>
876 inline constexpr
bool operator==(DynamicVerified<T>
const& ,
887 template <
typename T>
888 inline constexpr
bool operator==(std::nullptr_t ,
889 DynamicVerified<T>
const& )
899 template <
typename T>
900 inline constexpr
bool operator!=(DynamicVerified<T>
const& ,
911 template <
typename T>
912 inline constexpr
bool operator!=(std::nullptr_t ,
913 DynamicVerified<T>
const& )
921 template <
typename T>
923 verifyDynamicTypeOrNull(T*
const& param,
const char* paramName,
926 static_assert(traits::has_xr_type_tag_v<T>,
927 "Can only use verifyDynamicTypeOrNull on types with an " 928 "associated XrStructureType enum value.");
929 if (
nullptr == param) {
932 return {param, paramName, errorCode};
935 template <
typename T>
937 verifyDynamicType(T* param,
const char* paramName, XrResult errorCode)
939 static_assert(traits::has_xr_type_tag_v<T>,
940 "Can only use verifyDynamicType() on types with an " 941 "associated XrStructureType enum value.");
942 if (
nullptr == param) {
943 throw exceptions::type_error(
944 paramName,
nullptr, traits::xr_type_tag_v<T>, errorCode);
946 return {*param, paramName, errorCode};
949 template <
typename T>
951 verifyDynamicType(T& param,
const char* paramName, XrResult errorCode)
953 static_assert(traits::has_xr_type_tag_v<T>,
954 "Can only use verifyDynamicType() on types with an " 955 "associated XrStructureType enum value.");
956 return {param, paramName, errorCode};
959 template <
typename T,
typename U>
961 required_verified_cast(U*
const& param,
const char* paramName,
964 static_assert(traits::has_xr_type_tag_v<T>,
965 "Can only use required_verified_cast() with type params " 966 "that have an associated XrStructureType enum value.");
967 static_assert(!is_const_v<U> || is_const_v<T>,
968 "Can't use required_verify_cast() to cast away const.");
969 static_assert(!is_pointer_v<T>,
970 "Pass just the target type, not a pointer, " 971 "as the type param of required_verified_cast()");
972 static_assert(!is_reference_v<T>,
973 "Pass just the target type, not a reference, " 974 "as the type param of required_verified_cast()");
976 if (
nullptr == param) {
977 throw exceptions::type_error(
978 paramName,
nullptr, traits::xr_type_tag_v<T>, errorCode);
981 if (castResult ==
nullptr) {
982 throw exceptions::type_error(paramName, param->type,
983 traits::xr_type_tag_v<T>,
986 return {*castResult, paramName, errorCode};
989 template <
typename T,
typename U>
991 required_verified_cast(U& param,
const char* paramName, XrResult errorCode)
993 static_assert(traits::has_xr_type_tag_v<T>,
994 "Can only use required_verified_cast() with type params " 995 "that have an associated XrStructureType enum value.");
996 static_assert(!is_const_v<U> || is_const_v<T>,
997 "Can't use required_verify_cast() to cast away const.");
998 static_assert(!is_pointer_v<T>,
999 "Pass just the target type, not a pointer, " 1000 "as the type param of required_verified_cast()");
1001 static_assert(!is_reference_v<T>,
1002 "Pass just the target type, not a reference, " 1003 "as the type param of required_verified_cast()");
1007 if (castResult ==
nullptr) {
1008 throw exceptions::type_error(
1009 paramName, param.type, traits::xr_type_tag_v<T>, errorCode);
1011 return {*castResult, paramName, errorCode};
1014 template <
typename T,
typename U>
1016 required_verified_or_null_cast(U* param,
const char* paramName,
1019 static_assert(traits::has_xr_type_tag_v<T>,
1020 "Can only use required_verified_cast() with type params " 1021 "that have an associated XrStructureType enum value.");
1023 !is_const_v<U> || is_const_v<T>,
1024 "Can't use required_verified_or_null_cast() to cast away const.");
1025 if (
nullptr == param) {
1029 if (castResult ==
nullptr) {
1030 throw exceptions::type_error(paramName, param->type,
1031 traits::xr_type_tag_v<T>,
1034 return {*castResult, paramName, errorCode};
1039 #ifndef XRTRAITS_DOXYGEN 1041 template <
typename T>
1043 ensureNotNull(DynamicVerifiedOrNull<T>
const& param,
const char* paramName,
1046 static_assert(traits::has_xr_type_tag_v<T>,
1047 "Can only use ensureNotNull() on types with an " 1048 "associated XrStructureType enum value.");
1049 if (
nullptr == param) {
1050 throw exceptions::type_error(
1051 paramName,
nullptr, traits::xr_type_tag_v<T>, errorCode);
1053 return {*param, paramName, errorCode};
1056 #endif // !XRTRAITS_DOXYGEN 1058 template <
typename TargetType,
typename SourceType>
1060 getFromChain(SourceType* param,
const char* paramName, XrResult errorCode)
1062 static_assert(traits::is_xr_tagged_type_v<SourceType>,
1063 "Can only use getFromChain() on types known to have type " 1064 "and next members.");
1065 static_assert(!is_pointer_v<TargetType>,
1066 "Type parameter to getFromChain() should just be the " 1067 "structure type, not a pointer type.");
1068 static_assert(!is_reference_v<TargetType>,
1069 "Type parameter to getFromChain() should just be the " 1070 "structure type, not a reference type.");
1072 return {param, paramName, errorCode, detail::get_from_chain};
1075 template <
typename TargetType,
typename SourceType>
1077 traits::is_xr_tagged_type_v<SourceType>, DynamicVerified<TargetType>>
1078 getFromChain(SourceType& param,
const char* paramName, XrResult errorCode)
1080 static_assert(traits::is_xr_tagged_type_v<SourceType>,
1081 "Can only use getFromChain() on types known to have type " 1082 "and next members.");
1083 static_assert(!is_pointer_v<TargetType>,
1084 "Type parameter to getFromChain() should just be the " 1085 "structure type, not a pointer type.");
1086 static_assert(!is_reference_v<TargetType>,
1087 "Type parameter to getFromChain() should just be the " 1088 "structure type, not a reference type.");
1090 return {std::addressof(param), paramName, errorCode,
1091 detail::get_from_chain};
1094 template <
typename TargetType,
typename SourceType>
1096 getFromChain(DynamicVerified<SourceType>
const& param,
const char* paramName,
1099 static_assert(!is_pointer_v<TargetType>,
1100 "Type parameter to getFromChain() should just be the " 1101 "structure type, not a pointer type.");
1102 static_assert(!is_reference_v<TargetType>,
1103 "Type parameter to getFromChain() should just be the " 1104 "structure type, not a reference type.");
1105 return {param.get(), paramName, errorCode, detail::get_from_chain};
1108 template <
typename TargetType,
typename SourceType>
1110 tryGetFromChain(SourceType* param) noexcept
1112 static_assert(traits::is_xr_tagged_type_v<SourceType>,
1113 "Can only use tryGetFromChain() on types known to have " 1114 "type and next members.");
1115 static_assert(!is_pointer_v<TargetType>,
1116 "Type parameter to tryGetFromChain() should just be the " 1117 "structure type, not a pointer type.");
1118 static_assert(!is_reference_v<TargetType>,
1119 "Type parameter to tryGetFromChain() should just be the " 1120 "structure type, not a reference type.");
1122 return {param, detail::get_from_chain};
1125 template <
typename TargetType,
typename SourceType>
1127 traits::is_xr_tagged_type_v<SourceType>, DynamicVerifiedOrNull<TargetType>>
1128 tryGetFromChain(SourceType& param) noexcept
1130 static_assert(traits::is_xr_tagged_type_v<SourceType>,
1131 "Can only use tryGetFromChain() on types known to have " 1132 "type and next members.");
1133 static_assert(!is_pointer_v<TargetType>,
1134 "Type parameter to tryGetFromChain() should just be the " 1135 "structure type, not a pointer type.");
1136 static_assert(!is_reference_v<TargetType>,
1137 "Type parameter to tryGetFromChain() should just be the " 1138 "structure type, not a reference type.");
1140 return {std::addressof(param), detail::get_from_chain};
1143 template <
typename TargetType,
typename SourceType>
1145 tryGetFromChain(DynamicVerifiedOrNull<SourceType>
const& param) noexcept
1147 static_assert(!is_pointer_v<TargetType>,
1148 "Type parameter to tryGetFromChain() should just be the " 1149 "structure type, not a pointer type.");
1150 static_assert(!is_reference_v<TargetType>,
1151 "Type parameter to tryGetFromChain() should just be the " 1152 "structure type, not a reference type.");
1153 return {param.get(), detail::get_from_chain};
1156 template <
typename T>
1157 class DynamicVerifiedSpan :
public span<T, gsl::dynamic_extent>
1161 using base = span<T, gsl::dynamic_extent>;
1164 using size_type =
typename base::size_type;
1166 static_assert(traits::has_xr_type_tag_v<T>,
1167 "Can only use DynamicVerifiedSpan on types with an " 1168 "associated XrStructureType enum value.");
1174 constexpr DynamicVerifiedSpan(T* pointer, size_type sz,
1175 const char* paramName, XrResult errorCode)
1176 : span<T, gsl::dynamic_extent>(pointer, sz)
1178 if (pointer ==
nullptr) {
1179 throw exceptions::type_error(paramName,
nullptr,
1180 traits::xr_type_tag_v<T>,
1183 for (size_type i = 0; i < sz; ++i) {
1184 const auto t = (*this)[i].type;
1185 if (t != traits::xr_type_tag_v<T>) {
1186 throw exceptions::type_error(
1187 paramName, t, traits::xr_type_tag_v<T>, i,
1194 template <
typename T>
1196 make_dynamic_verified_span(T* pointer, std::ptrdiff_t size,
1197 const char* paramName, XrResult errorCode)
1200 traits::has_xr_type_tag_v<T>,
1201 "Can only use make_dynamic_verified_span on types with an " 1202 "associated XrStructureType enum value.");
1203 return {pointer, size, paramName, errorCode};
1211 #undef XRTRAITS_NOEXCEPT_IF_NOT_RECHECKING 1213 #endif // defined(XRTRAITS_HAVE_EXCEPTIONS) && Main namespace for these C++ OpenXR utilities.
Definition: GetChained.h:26
#define XRTRAITS_NODISCARD
Compatibility wrapper for [[nodiscard]]
Definition: Attributes.h:24
TargetType xr_tagged_dynamic_cast(SourceType &&source)
Definition: TaggedDynamicCast.h:53
C++ type traits related to OpenXR, and some other compile-time functionality.
Header providing a slightly-riskier relative of xr_tagged_dynamic_cast() that works on void pointers ...
#define GSL_ASSUME(X)
Definition: GSLWrap.h:23
Header providing xr_get_chained_struct, to extract a struct of a given type from a next chain...
Header defining macros corresponding to various C++ attributes.
Header providing a dynamic_cast equivalent for OpenXR tagged types, xr_tagged_dynamic_cast().
#define Expects(X)
When GSL is available, normally asserts a precondition.
Definition: GSLWrap.h:29
Header with common utilities used by multiple headers.
Header wrapping or stubbing GSL.