Distributed Ranges
Loading...
Searching...
No Matches
index.hpp
1// SPDX-FileCopyrightText: Intel Corporation
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#pragma once
6
7#include <any>
8#include <concepts>
9#include <limits>
10#include <tuple>
11
12namespace dr {
13
14namespace {
15template <typename T, std::size_t I, typename U = std::any>
16concept TupleElementGettable = requires(T tuple) {
17 { std::get<I>(tuple) } -> std::convertible_to<U>;
18};
19} // namespace
20
21template <typename T, typename... Args>
22concept TupleLike =
23 requires {
24 typename std::tuple_size<std::remove_cvref_t<T>>::type;
25 requires std::same_as<
26 std::remove_cvref_t<
27 decltype(std::tuple_size_v<std::remove_cvref_t<T>>)>,
28 std::size_t>;
29 } && sizeof...(Args) == std::tuple_size_v<std::remove_cvref_t<T>> &&
30 []<std::size_t... I>(std::index_sequence<I...>) {
31 return (TupleElementGettable<T, I, Args> && ...);
32 }(std::make_index_sequence<std::tuple_size_v<std::remove_cvref_t<T>>>());
33
34template <std::integral T = std::size_t> class index {
35public:
36 using index_type = T;
37
38 using first_type = T;
39 using second_type = T;
40
41 constexpr index_type operator[](index_type dim) const noexcept {
42 if (dim == 0) {
43 return first;
44 } else {
45 return second;
46 }
47 }
48
49 template <std::integral U>
50 requires(std::numeric_limits<U>::max() >= std::numeric_limits<T>::max())
51 constexpr operator index<U>() const noexcept {
52 return index<U>(first, second);
53 }
54
55 template <std::integral U>
56 requires(std::numeric_limits<U>::max() < std::numeric_limits<T>::max())
57 constexpr explicit operator index<U>() const noexcept {
58 return index<U>(first, second);
59 }
60
61 constexpr index(index_type first, index_type second)
62 : first(first), second(second) {}
63
64 template <TupleLike<T, T> Tuple>
65 constexpr index(Tuple tuple)
66 : first(std::get<0>(tuple)), second(std::get<1>(tuple)) {}
67
68 template <std::integral U> constexpr index(std::initializer_list<U> tuple) {
69 assert(tuple.size() == 2);
70 first = *tuple.begin();
71 second = *(tuple.begin() + 1);
72 }
73
74 constexpr bool operator==(const index &) const noexcept = default;
75 constexpr bool operator<(const index &other) const noexcept
76 requires(std::totally_ordered<T>)
77 {
78 if (first < other.first) {
79 return true;
80 }
81 if (first == other.first && second < other.second) {
82 return true;
83 }
84 return false;
85 }
86
87 template <std::size_t Index>
88 constexpr T get() const noexcept
89 requires(Index <= 1)
90 {
91 if constexpr (Index == 0) {
92 return first;
93 }
94 if constexpr (Index == 1) {
95 return second;
96 }
97 }
98
99 index() = default;
100 ~index() = default;
101 index(const index &) = default;
102 index &operator=(const index &) = default;
103 index(index &&) = default;
104 index &operator=(index &&) = default;
105
106 index_type first;
107 index_type second;
108};
109
110} // namespace dr
111
112namespace std {
113
114template <std::size_t Index, std::integral I>
115struct tuple_element<Index, dr::index<I>>
116 : tuple_element<Index, std::tuple<I, I>> {};
117
118template <std::integral I>
119struct tuple_size<dr::index<I>> : integral_constant<std::size_t, 2> {};
120
121template <std::size_t Index, std::integral I>
122inline constexpr I get(dr::index<I> index)
123 requires(Index <= 1)
124{
125 if constexpr (Index == 0) {
126 return index.first;
127 }
128 if constexpr (Index == 1) {
129 return index.second;
130 }
131}
132
133} // namespace std
Definition: index.hpp:34
Definition: index.hpp:22
Definition: index.hpp:16