XRTraits C++ OpenXR Utilities
PolymorphicSpan.h
Go to the documentation of this file.
1 // Copyright 2018-2019, Collabora, Ltd.
2 // SPDX-License-Identifier: BSL-1.0
3 /*!
4  * @file
5  * @brief Header
6  * @author Ryan Pavlik <ryan.pavlik@collabora.com>
7  */
8 
9 #pragma once
10 #include "Common.h"
11 
12 #include "DynamicVerified.h"
13 
14 // Needs DynamicVerified and optional
15 #if defined(XRTRAITS_HAVE_DYNAMIC_VERIFIED) && defined(XRTRAITS_HAVE_OPTIONAL)
16 
17 /*!
18  * Defined after including PolymorphicSpan.h if the compiler and config
19  * requirements are satisfied to provide PolymorphicSpan functionality.
20  */
21 #define XRTRAITS_HAVE_POLYMORPHIC_SPAN
22 
23 // Internal Includes
24 // - none
25 
26 // Library Includes
27 // - none
28 
29 // Standard Includes
30 #include <optional>
31 
32 namespace xrtraits {
33 
34 using std::nullopt;
35 using std::optional;
36 
37 /*! Stores a pointer and a size like gsl::span<T> except here, we **know** that
38  * the static type is not actually the dynamic type, so it's not safe to
39  * actually index yet.
40  */
41 template <typename T> class PolymorphicSpan;
42 
43 /*! Similar to gsl::make_span, but the resulting span is only useful for passing
44  * to required_verified_span_cast().
45  */
46 template <typename T>
47 XRTRAITS_NODISCARD inline constexpr PolymorphicSpan<T>
48 make_polymorphic_span(T* pointer, std::ptrdiff_t size,
49  const char* paramName = nullptr,
50  XrResult errorCode = exceptions::DEFAULT_TYPE_ERROR_CODE);
51 
52 template <typename T> class PolymorphicSpan
53 {
54 public:
55  //! Type used for size
56  using size_type = std::ptrdiff_t;
57 
58  /*! Constructor from a pointer and a size (and optional param name and
59  * error code)
60  */
61  constexpr PolymorphicSpan(T* pointer, size_type sz,
62  const char* paramName = nullptr,
63  optional<XrResult> const& errorCode = nullopt)
64  : ptr_(pointer), size_(sz), paramName_(paramName),
65  errorCode_(errorCode)
66  {}
67 
68  //! Get the size of the span
69  constexpr size_type size() const { return size_; }
70 
71  //! Get the associated data pointer
72  constexpr T* data() const { return ptr_; }
73 
74  //! Function to perform a cast
75  template <typename U>
76  constexpr DynamicVerifiedSpan<U>
77  cast(const char* paramName = nullptr,
78  optional<XrResult> const& errorCode = nullopt) const
79  {
80  static_assert(
81  traits::same_constness<T, U>,
82  "Can't change constness with PolymorphicSpan<T>::cast<U>");
83  static_assert(traits::has_xr_type_tag_v<U>,
84  "Can only cast with PolymorphicSpan<T>::cast<U> "
85  "to a type with a known tag");
86  auto result = errorCode.value_or(
87  errorCode_.value_or(exceptions::DEFAULT_TYPE_ERROR_CODE));
88  auto param = (paramName != nullptr) ? paramName : paramName_;
89  if (ptr_ == nullptr) {
90  throw exceptions::type_error(param, nullptr,
91  traits::xr_type_tag_v<U>,
92  size_, result);
93  }
94  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
95  return {reinterpret_cast<U*>(ptr_), size_, paramName, result};
96  }
97 
98 private:
99  T* ptr_;
100  size_type size_;
101  const char* paramName_;
102  optional<XrResult> errorCode_;
103 };
104 
105 /*! Takes a PolymorphicSpan and tries to cast it to a DynamicVerifiedSpan,
106  * throwing an exception in the case of dynamic type mismatch.
107  *
108  * If you don't supply a paramName and errorCode, it will default to the ones
109  * passed to make_polymorphic_span()
110  */
111 template <typename TargetType, typename SourceType>
112 XRTRAITS_NODISCARD inline constexpr DynamicVerifiedSpan<TargetType>
113 required_verified_span_cast(PolymorphicSpan<SourceType> const& source,
114  const char* paramName = nullptr,
115  optional<XrResult> const& errorCode = nullopt);
116 template <typename T>
117 XRTRAITS_NODISCARD inline constexpr PolymorphicSpan<T>
118 make_polymorphic_span(T* pointer, std::ptrdiff_t size, const char* paramName,
119  XrResult errorCode)
120 {
121  return {pointer, size, paramName, errorCode};
122 }
123 
124 template <typename TargetType, typename SourceType>
125 XRTRAITS_NODISCARD inline constexpr DynamicVerifiedSpan<TargetType>
126 required_verified_span_cast(PolymorphicSpan<SourceType> const& source,
127  const char* paramName,
128  optional<XrResult> const& errorCode)
129 {
130  static_assert(
131  traits::same_constness<SourceType, TargetType>,
132  "Can't change constness with required_verified_span_cast");
133  static_assert(traits::has_xr_type_tag_v<TargetType>,
134  "Can only cast with required_verified_span_cast "
135  "to a type with a known tag");
136  return source.template cast<TargetType>(paramName, errorCode);
137 }
138 
139 
140 #endif // defined(XRTRAITS_HAVE_DYNAMIC_VERIFIED) && defined(XRTRAITS_HAVE_OPTIONAL)
Main namespace for these C++ OpenXR utilities.
Definition: GetChained.h:26
#define XRTRAITS_NODISCARD
Compatibility wrapper for [[nodiscard]]
Definition: Attributes.h:24
Header with common utilities used by multiple headers.
Header providing type-enforced verification of OpenXR "tagged types".