ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
type_registry.hpp
1// This file is part of the ACTS project.
2//
3// Copyright (C) 2016 CERN for the benefit of the ACTS project
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9#pragma once
10
11// Project include(s)
12#include "detray/definitions/detail/qualifiers.hpp"
13#include "detray/definitions/indexing.hpp"
14#include "detray/utils/concepts.hpp"
15#include "detray/utils/invalid_values.hpp"
16#include "detray/utils/logging.hpp"
17#include "detray/utils/type_list.hpp"
18
19// System include(s)
20#include <limits>
21#include <type_traits>
22#include <utility>
23
24namespace detray {
25
26namespace types {
27
32template <concepts::type_id ID, typename... registered_types>
33class registry {
34 public:
36 using id = ID;
38 using type_list = detray::types::list<registered_types...>;
39
41 enum : std::size_t {
42 n_types = sizeof...(registered_types),
43 e_any = sizeof...(registered_types),
44 e_unknown = sizeof...(registered_types) + 1,
45 };
46
52 DETRAY_HOST_DEVICE static constexpr bool is_valid(
53 const std::size_t type_idx) {
54 return type_idx < n_types;
55 }
56
60 template <typename id_t = id>
61 requires(!std::convertible_to<id_t, std::size_t>)
62 DETRAY_HOST_DEVICE static constexpr bool is_valid(const id_t type_id) {
63 return static_cast<std::size_t>(type_id) < n_types;
64 }
65
66};
67
68} // namespace types
69
70namespace concepts {
71
74template <typename R>
78
79} // namespace concepts
80
81namespace types {
82
88template <typename orig_types_t, class type_selector_t>
89DETRAY_DEVICE_CONSTANT constexpr auto index_map_v =
90 detray::types::filtered_indices<orig_types_t, type_selector_t>(
92
101template <concepts::type_registry registry_t, class type_selector_t>
102class mapped_registry : public registry_t {
103 public:
105 using id = typename registry_t::id;
107 using orig_types = typename registry_t::type_list;
109 using type_list =
110 decltype(detray::types::filtered_list<orig_types, type_selector_t>());
111
113 enum : std::size_t {
114 n_types = detray::types::size<type_list>,
115 e_any = detray::types::size<type_list>,
116 e_unknown = detray::types::size<type_list> + 1u,
117 };
118
125 DETRAY_HOST_DEVICE static constexpr bool is_valid(
126 const std::size_t filtered_type_idx) {
127 return filtered_type_idx < n_types;
128 }
129
133 template <typename id_t = id>
134 requires(!std::convertible_to<id_t, std::size_t>)
135 DETRAY_HOST_DEVICE static constexpr bool is_valid(const id_t orig_id) {
136 if (static_cast<std::size_t>(orig_id) >= index_map().size()) {
137 return false;
138 } else {
139 return mapped_index(orig_id) < n_types;
140 }
141 }
142
143
145 DETRAY_HOST_DEVICE
146 static consteval auto index_map() {
147 return detray::types::filtered_indices<orig_types, type_selector_t>(
149 }
150
155 DETRAY_HOST_DEVICE
156 static constexpr std::size_t mapped_index(const std::size_t orig_idx) {
157 return index_map_v<orig_types, type_selector_t>[orig_idx];
158 }
159
163 DETRAY_HOST_DEVICE
164 static constexpr std::size_t mapped_index(const id orig_id) {
165 return index_map_v<orig_types, type_selector_t>[static_cast<std::size_t>(
166 orig_id)];
167 }
168
171 DETRAY_HOST_DEVICE
172 static constexpr std::size_t original_index(const std::size_t pos) {
173 std::size_t j{0u};
174 for (std::size_t i : index_map_v<orig_types, type_selector_t>) {
175 if (i == pos) {
176 assert(registry_t::is_valid(j));
177 return j;
178 }
179 j++;
180 }
181 return detray::detail::invalid_value<std::size_t>();
182 }
183
186 DETRAY_HOST_DEVICE
187 static constexpr id original_id(const std::size_t pos) {
188 return static_cast<id>(original_index(pos));
189 }
190};
191
192} // namespace types
193
194namespace concepts {
195
198template <typename R>
203
204} // namespace concepts
205
206namespace types {
207
211template <concepts::type_id ID, typename... Ts>
212struct get_size<registry<ID, Ts...>>
213 : std::integral_constant<std::size_t, sizeof...(Ts)> {};
214
215template <typename R, class S>
217 : std::integral_constant<std::size_t, mapped_registry<R, S>::n_types> {};
218
219
223template <typename T, std::size_t I, concepts::type_id ID, typename... Ts>
224struct contains_impl<T, I, registry<ID, Ts...>>
225 : public contains_impl<T, I, typename registry<ID, Ts...>::type_list> {};
226
229template <typename T, std::size_t I, typename R, class S>
230struct contains_impl<T, I, mapped_registry<R, S>> {
231 // Figure out which type list to check
232 // (use original list if 'T' is from there, otherwise try filtered list)
239 std::conditional_t<contains<orig_list_t, T>, orig_list_t, filt_list_t>;
240
243
245 static constexpr bool value = base_t::value;
246
247 // Depending on which type list the type belongs to, map the index
249 static constexpr std::size_t mapped_idx =
250 std::same_as<type_list_t, orig_list_t>
252 : base_t::pos;
253
254 // The type is not contained in 'type_list', the position will be invalid:
255 // Do not pass that to the range-checked array of the filtered indices
257 static constexpr std::size_t pos =
258 !base_t::value ? std::numeric_limits<std::size_t>::max() : mapped_idx;
259};
260
261
266template <std::size_t N, concepts::type_id ID, typename... Ts>
267struct get_at<N, registry<ID, Ts...>> {
268 static_assert(registry<ID, Ts...>::is_valid(N),
269 "Index out of range in type registry 'at'");
271 using type =
272 typename get_at<N, typename registry<ID, Ts...>::type_list>::type;
273};
274
276template <std::size_t N, typename R, class S>
277struct get_at<N, mapped_registry<R, S>> {
278 static_assert(mapped_registry<R, S>::is_valid(N),
279 "Index out of range in mapped type registry 'at'");
281 using type =
283};
284
285
288
291template <typename = void, typename = void>
292struct get_id {};
293
295template <typename T, concepts::type_id ID, typename... Ts>
296struct get_id<T, registry<ID, Ts...>> {
298 static constexpr ID value =
299 static_cast<ID>(position<typename registry<ID, Ts...>::type_list, T>);
300
301 static_assert(contains<typename registry<ID, Ts...>::type_list, T>,
302 "Unknown type in 'get id' for type registry");
304 "Unmatched type ID in type registry 'id'");
305};
306
309template <typename T, typename R, class S>
310struct get_id<T, mapped_registry<R, S>> {
311 // Figure out which type list to check
312 // (use original list if 'T' is from there, otherwise try filtered list)
321 std::conditional_t<contains<orig_list_t, T>, orig_list_t, filt_list_t>;
322
323 static_assert(std::same_as<type_list_t, orig_list_t> ||
324 (std::same_as<type_list_t, filt_list_t> &&
325 contains<filt_list_t, T>),
326 "Unknown type in 'get id' for mapped type registry");
327
329 using id_t = typename mapped_reg_t::id;
331 static constexpr id_t value =
332 contains<orig_list_t, T>
333 ? static_cast<id_t>(position<orig_list_t, T>)
334 : mapped_reg_t::original_id(position<filt_list_t, T>);
335};
336
337template <typename R, typename T>
338inline constexpr R::id id{get_id<T, R>::value};
340
343template <std::size_t I, typename = void>
344struct get_type {};
345
347template <std::size_t I, typename ID, typename... Ts>
348struct get_type<I, registry<ID, Ts...>> {
349 static_assert(registry<ID, Ts...>::is_valid(I),
350 "Unmatched type ID in type registry 'get'");
351
353 using type = at<registry<ID, Ts...>, I>;
354};
355
357template <std::size_t I, typename R, class S>
358struct get_type<I, mapped_registry<R, S>> {
359 static_assert(
361 "Unmatched type ID in mapped type registry 'get'");
362
364 using type =
365 at<mapped_registry<R, S>, mapped_registry<R, S>::mapped_index(I)>;
366};
367
368template <typename R, auto I>
369using get = typename get_type<static_cast<std::size_t>(I), R>::type;
371
374template <std::size_t I, typename = void>
375struct cast_impl_id {};
376
378template <std::size_t I, typename ID, typename... Ts>
379struct cast_impl_id<I, registry<ID, Ts...>> {
380 static_assert(registry<ID, Ts...>::is_valid(I),
381 "Cannot cast to ID: Invalid index for type registry");
382
384 static constexpr ID value = static_cast<ID>(I);
385};
386
388template <std::size_t I, typename R, class S>
390 static_assert(
392 "Cannot cast to ID: Invalid index for ,apped type registry");
393
397 static constexpr ID value = static_cast<ID>(I);
398};
399
400template <std::size_t I, typename = void>
402
404template <std::size_t I, typename ID, typename... Ts>
405struct cast_impl_idx<I, registry<ID, Ts...>> {
406 static_assert(registry<ID, Ts...>::is_valid(I),
407 "Cannot cast to index: Invalid index for type registry");
408
410 static constexpr std::size_t value = I;
411};
412
414template <std::size_t I, typename R, class S>
416 static_assert(
418 "Cannot cast to index: Invalid index for ,apped type registry");
419
421 static constexpr std::size_t value = mapped_registry<R, S>::mapped_index(I);
422};
423
424template <typename R, std::size_t I>
425inline constexpr R::id id_cast = cast_impl_id<I, R>::value;
426
427template <typename R, auto I>
428inline constexpr std::size_t index_cast =
429 cast_impl_idx<static_cast<std::size_t>(I), R>::value; // NOLINT
431
433
448template <concepts::type_registry registry_t, typename functor_t,
449 typename... Args, std::size_t current_idx = 0u,
450 std::size_t... remaining_idcs>
451 requires(std::invocable<functor_t,
452 const types::front<typename registry_t::type_list>&,
453 Args...>)
454DETRAY_HOST_DEVICE constexpr decltype(auto) visit_helper(
455 const std::size_t idx,
456 std::index_sequence<current_idx, remaining_idcs...> /*seq*/,
457 Args&&... args) {
458 // Check if the current tuple index is matched to the target index
460 if (registry_t::mapped_index(idx) == current_idx) {
461 return functor_t{}(types::at<registry_t, current_idx>{},
462 std::forward<Args>(args)...);
463 }
464 } else {
465 if (idx == current_idx) {
466 return functor_t{}(types::at<registry_t, current_idx>{},
467 std::forward<Args>(args)...);
468 }
469 }
470
471 // Check the next index
472 using return_t = std::invoke_result_t<
473 functor_t, const types::front<typename registry_t::type_list>&, Args...>;
474
475 if constexpr (sizeof...(remaining_idcs) >= 1u) {
476 using next_elem_t = types::at<registry_t, current_idx + 1u>;
477 using next_return_t =
478 std::invoke_result_t<functor_t, const next_elem_t&, Args...>;
479 static_assert(
480 std::same_as<return_t, next_return_t>,
481 "Functor return type must be the same for all elements of the "
482 "tuple.");
483
484 return visit_helper<registry_t, functor_t>(
485 idx, std::index_sequence<remaining_idcs...>{},
486 std::forward<Args>(args)...);
487 } else if constexpr (std::is_same_v<return_t, void>) {
488 return;
489 } else {
490 return return_t{};
491 }
492}
493
501template <concepts::type_registry registry_t, typename functor_t,
502 typename... Args>
503DETRAY_HOST_DEVICE constexpr decltype(auto) visit(const std::size_t idx,
504 Args&&... args) {
505 return visit_helper<registry_t, functor_t>(
506 idx, std::make_index_sequence<registry_t::n_types>{},
507 std::forward<Args>(args)...);
508}
509
517template <concepts::type_registry registry_t, typename functor_t,
518 typename... Args>
519DETRAY_HOST_DEVICE constexpr decltype(auto) visit(
520 const typename registry_t::id type_id, Args&&... args) {
521 assert(registry_t::is_valid(type_id));
522
523 return visit<registry_t, functor_t>(static_cast<std::size_t>(type_id),
524 std::forward<Args>(args)...);
525}
526
527} // namespace types
528
529} // namespace detray
Select a number of types from another registry and map their IDs to a continuous range of new type in...
Definition type_registry.hpp:102
static constexpr std::size_t mapped_index(const std::size_t orig_idx)
Return the filtered position corresponding to an original position.
Definition type_registry.hpp:156
static consteval auto index_map()
Definition type_registry.hpp:146
static constexpr bool is_valid(const std::size_t filtered_type_idx)
Definition type_registry.hpp:125
typename registry_t::id id
Make the original type ids accessible.
Definition type_registry.hpp:105
decltype(detray::types::filtered_list< orig_types, type_selector_t >()) type_list
Make the filtered types accessible.
Definition type_registry.hpp:109
static constexpr std::size_t mapped_index(const id orig_id)
Return the filtered position corresponding to an original ID.
Definition type_registry.hpp:164
static constexpr bool is_valid(const id_t orig_id)
Check whether an original ID selects a type retained by the mapping.
Definition type_registry.hpp:135
static constexpr id original_id(const std::size_t pos)
Definition type_registry.hpp:187
static constexpr std::size_t original_index(const std::size_t pos)
Definition type_registry.hpp:172
typename registry_t::type_list orig_types
Make the original types accessible.
Definition type_registry.hpp:107
match types with indices/identifiers and vice versa.
Definition type_registry.hpp:33
ID id
Definition type_registry.hpp:36
static constexpr bool is_valid(const std::size_t type_idx)
Definition type_registry.hpp:52
static constexpr bool is_valid(const id_t type_id)
Check whether an identifier corresponds to a registered type.
Definition type_registry.hpp:62
detray::types::list< registered_types... > type_list
Definition type_registry.hpp:38
Mapped type registry concepts.
Definition type_registry.hpp:199
Type identifier concept.
Definition concepts.hpp:36
Definition type_list.hpp:363
Type registry concepts.
Definition type_registry.hpp:75
Detray include(s).
Definition array_operators.hpp:18
typename mapped_registry< R, S >::id ID
Identifier type of the original registry.
Definition type_registry.hpp:395
static constexpr ID value
Identifier corresponding to the compile-time mapped index.
Definition type_registry.hpp:397
static constexpr ID value
Identifier corresponding to the compile-time index.
Definition type_registry.hpp:384
Get the type corresponding to an ID.
Definition type_registry.hpp:375
static constexpr std::size_t value
Filtered index corresponding to the original index.
Definition type_registry.hpp:421
static constexpr std::size_t value
Registry index corresponding to the compile-time index.
Definition type_registry.hpp:410
Definition type_registry.hpp:401
contains_impl< T, I, type_list_t > base_t
Lookup result in the chosen list.
Definition type_registry.hpp:242
std::conditional_t< contains< orig_list_t, T >, orig_list_t, filt_list_t > type_list_t
List in which T is looked up.
Definition type_registry.hpp:238
static constexpr std::size_t pos
Position reported by this trait, or std::size_t's maximum when absent.
Definition type_registry.hpp:257
typename mapped_registry< R, S >::type_list filt_list_t
Filtered registry's ordered type list.
Definition type_registry.hpp:236
typename mapped_registry< R, S >::orig_types orig_list_t
Original registry's ordered type list.
Definition type_registry.hpp:234
static constexpr std::size_t mapped_idx
Position of T in the filtered list when it came from the original list.
Definition type_registry.hpp:249
static constexpr bool value
Whether T occurs in the selected list.
Definition type_registry.hpp:245
Does the list contain a particular type?
Definition type_list.hpp:48
typename get_at< N, typename mapped_registry< R, S >::type_list >::type type
Type at filtered position N in the mapped registry.
Definition type_registry.hpp:281
typename get_at< N, typename registry< ID, Ts... >::type_list >::type type
Type at position N in the registry.
Definition type_registry.hpp:271
Access the N-th type.
Definition type_list.hpp:117
typename mapped_reg_t::type_list filt_list_t
Type list after applying the selector.
Definition type_registry.hpp:318
typename mapped_reg_t::id id_t
Identifier type shared with the original registry.
Definition type_registry.hpp:329
mapped_registry< R, S > mapped_reg_t
Mapped registry being queried.
Definition type_registry.hpp:314
typename mapped_reg_t::orig_types orig_list_t
Type list before applying the selector.
Definition type_registry.hpp:316
std::conditional_t< contains< orig_list_t, T >, orig_list_t, filt_list_t > type_list_t
List used to resolve T, chosen from the original or filtered list.
Definition type_registry.hpp:320
static constexpr id_t value
Identifier of T in the original registry.
Definition type_registry.hpp:331
static constexpr ID value
Identifier value assigned to T by its position in the registry.
Definition type_registry.hpp:298
Traits for the type registry.
Definition type_registry.hpp:292
Number of types in the list.
Definition type_list.hpp:35
at< mapped_registry< R, S >, mapped_registry< R, S >::mapped_index(I)> type
Type selected by original identifier value I.
Definition type_registry.hpp:364
at< registry< ID, Ts... >, I > type
Type registered under identifier value I.
Definition type_registry.hpp:353
Get the type corresponding to an ID.
Definition type_registry.hpp:344
type list implementation
Definition type_list.hpp:30