XRTraits C++ OpenXR Utilities
TaggedCastCommon.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 shared between the two type-safe cast headers.
6  * @author Ryan Pavlik <ryan.pavlik@collabora.com>
7  */
8 
9 #pragma once
10 
11 // IWYU pragma: private
12 // IWYU pragma: friend "Tagged.*Cast\.h"
13 
14 #include "../Common.h"
15 
16 #ifdef XRTRAITS_HAVE_CONSTEXPR_IF
17 
18 /*!
19  * Defined after including any of the cast headers or GetChained.h if the compiler and config
20  * requirements are satisfied to provide at least some cast/get-chained functionality.
21  *
22  * Without exceptions, casts to reference types are unavailable.
23  */
24 #define XRTRAITS_HAVE_CASTS
25 
26 // Internal Includes
27 #include "../Common.h"
28 #include "../traits/APITraits.h"
29 
30 // Library Includes
31 #include <openxr/openxr.h>
32 
33 // Standard Includes
34 #include <type_traits>
35 
36 namespace xrtraits {
37 namespace casts {
38 
39 #ifndef XRTRAITS_DOXYGEN
40  namespace detail {
41 
42  using ::std::add_pointer_t;
43  using ::std::enable_if_t;
44  using ::std::integral_constant;
45  using ::std::is_const;
46  using ::std::is_pointer;
47  using ::std::remove_const_t;
48  using ::std::remove_pointer_t;
49  using namespace ::xrtraits::traits::detail;
50 
51  /*! Alias to shorten finding constness of pointed/referred to
52  * object.
53  */
54  template <typename T>
55  constexpr bool points_or_refers_to_const_v =
56  is_const_v<detail::remove_reference_pointer_t<T>>;
57 
58  /*! Alias to simplify conditional for selecting
59  * perform_pointer_reinterpret_cast implementation path
60  */
61  template <typename T>
62  constexpr bool points_to_const_v =
63  is_const_v<remove_pointer_t<T>>;
64  /*! Alias to simplify conditional for selecting
65  * perform_pointer_reinterpret_cast implementation path
66  */
67  template <typename T>
68  constexpr bool is_pointer_to_const_v =
69  is_pointer_v<T>&& points_to_const_v<T>;
70  /*! Alias to simplify conditional for selecting
71  * perform_pointer_reinterpret_cast implementation path
72  */
73  template <typename T>
74  constexpr bool
75  is_pointer_to_nonconst_v = is_pointer_v<T> &&
76  (!points_to_const_v<T>);
77 
78  /*! Alias to simplify conditional for selecting
79  * perform_pointer_reinterpret_cast implementation path
80  */
81  template <typename T, typename U>
82  constexpr bool pointed_to_constness_is_equal_v =
83  points_to_const_v<T> == points_to_const_v<U>;
84  /*! Reinterpret a pointer, optionally adding (but never
85  * removing) const qualification to the pointed-to type.
86  */
87  template <typename TargetType, typename SourceType>
88  inline TargetType
89  perform_pointer_reinterpret_cast(SourceType* source)
90  {
91  using Source = add_pointer_t<SourceType>;
92  static_assert(!(is_pointer_to_const_v<
93  add_pointer_t<SourceType>> &&
94  is_pointer_to_nonconst_v<TargetType>),
95  "Can't remove constness with "
96  "perform_pointer_reinterpret_cast");
97  if constexpr (pointed_to_constness_is_equal_v<
98  SourceType, TargetType>) {
99  return reinterpret_cast<TargetType>( // NOLINT
100  source);
101 
102  } else { // NOLINT
103  static_assert(
104  is_pointer_to_nonconst_v<Source> &&
105  is_pointer_to_const_v<TargetType>,
106  "If constness doesn't match, must have "
107  "ptr-to-non-const source and ptr-to-const "
108  "target.");
109  using TargetNonConst =
110  add_pointer_t<remove_const_t<
111  remove_pointer_t<TargetType>>>;
112  auto t =
113  reinterpret_cast<TargetNonConst>( // NOLINT
114  source);
115 
116  return const_cast<TargetType>(t); // NOLINT
117  }
118  }
119 
120  template <typename T> inline auto get_pointer(T&& obj)
121  {
122  if constexpr (is_pointer_v<remove_reference_t<T>>) {
123  return obj;
124  } else { // NOLINT(readability-else-after-return)
125  return &obj;
126  }
127  }
128 
129  template <typename TargetType, typename SourceType>
130  inline TargetType
131  perform_dereferencing_reinterpret_cast(SourceType&& source)
132  {
133  constexpr bool isTargetPtr = is_pointer_v<TargetType>;
134 
135  auto sourcePtr = get_pointer(source);
136  if constexpr (isTargetPtr) {
137  return perform_pointer_reinterpret_cast<
138  TargetType>(sourcePtr);
139  } else { // NOLINT(readability-else-after-return)
140 
141  return *perform_pointer_reinterpret_cast<
142  add_pointer_t<TargetType>>(sourcePtr);
143  }
144  }
145 
146  /*! Get the type member of the struct pointed/referred to by o.
147  *
148  * That is, performs o->type or o.type, as appropriate.
149  *
150  * For use in generic code that might get a pointer or a
151  * reference type and doesn't want to duplicate implementation.
152  */
153  template <typename T>
154  constexpr XrStructureType
155  get_type(T&& o, std::enable_if_t<traits::is_xr_tagged_type_v<T>,
156  void*> /*only for sfinae*/
157  = nullptr)
158  {
159  static_assert(
160  traits::is_xr_tagged_type_v<T>,
161  "Can only use get_type() on a pointer/reference to "
162  "a (possibly const) XR tagged type.");
163  if constexpr (is_pointer_v<
164  std::remove_reference_t<T>>) {
165  return o->type;
166  } else { // NOLINT(readability-else-after-return)
167  return o.type;
168  }
169  }
170  } // namespace detail
171 
172 #endif // !XRTRAITS_DOXYGEN
173 
174 } // namespace casts
175 
176 } // namespace xrtraits
177 #endif // XRTRAITS_HAVE_CONSTEXPR_IF
178 
Main namespace for these C++ OpenXR utilities.
Definition: GetChained.h:26
constexpr bool is_pointer_v
Variable template wrapping std::is_pointer<T>::value.
Definition: Common.h:23