-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathiterable_array.cpp
More file actions
119 lines (98 loc) · 3.57 KB
/
iterable_array.cpp
File metadata and controls
119 lines (98 loc) · 3.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// cl .\iterable_array.cpp /W4 /Zc:__cplusplus /EHsc /std:c++latest /experimental:module
// .\iterable_array.exe
#include <concepts>
#include <iostream>
#include <tuple>
#include <utility>
#include <vector>
template <typename T>
concept is_iterable = requires (T array_like) {
{ array_like.has_next() } -> std::convertible_to<bool>;
{ array_like.next() } -> std::same_as<uint32_t>;
{ array_like.reset() };
};
template <is_iterable T>
constexpr std::size_t count(T array) {
array.reset();
std::size_t count = 0;
while (array.has_next()) {
array.next();
count++;
}
return count;
}
template <typename T>
constexpr std::size_t count(T&& array) {
return count(array);
}
struct iterable_array {
constexpr inline iterable_array() noexcept = default;
constexpr inline iterable_array(const iterable_array&) noexcept = default;
constexpr inline iterable_array(const std::size_t s)
: array(s) {}
constexpr inline ~iterable_array() noexcept = default;
std::vector<uint32_t> array{};
std::size_t index = 0;
constexpr inline void reset() { index = 0; }
constexpr inline bool has_next() const noexcept { return index < array.size(); }
constexpr inline std::uint32_t next() {
index++;
return array[index - 1];
}
};
consteval [[nodiscard]] std::size_t __cdecl count_iterable_array() {
static_assert(std::is_constant_evaluated());
return count(iterable_array(10));
}
namespace std {
template <>
struct tuple_size<iterable_array> : integral_constant<std::size_t, 2> {};
template <>
struct tuple_element<0U, iterable_array> {
using type = vector<uint32_t>;
};
template <>
struct tuple_element<1U, iterable_array> {
using type = size_t;
};
template <size_t I>
requires (I < tuple_size<iterable_array>::value)
typename tuple_element<I, iterable_array>::type& get(iterable_array& itrarray) {
if constexpr (I == 0)
return itrarray.array;
else /* constexpr */
return itrarray.index;
}
template <size_t I>
requires (I < tuple_size<iterable_array>::value)
typename const tuple_element<I, iterable_array>::type& get(const iterable_array& itrarray) {
if constexpr (I == 0)
return itrarray.array;
else /* constexpr */
return itrarray.index;
}
template <size_t I>
requires (I < tuple_size<iterable_array>::value)
typename tuple_element<I, iterable_array>::type&& get(iterable_array&& itrarray) {
if constexpr (I == 0)
return std::forward<tuple_element<0U, iterable_array>::type>(itrarray.array);
else /* constexpr */
return std::forward<tuple_element<1U, iterable_array>::type>(itrarray.index);
}
} // namespace std
int main(void) {
static_assert(std::tuple_size<iterable_array>::value == 2);
static_assert(std::tuple_size_v<iterable_array> == 2);
static_assert(std::is_same_v<std::tuple_element<0, iterable_array>::type, std::vector<std::uint32_t>>);
static_assert(std::is_same_v<std::tuple_element<1, iterable_array>::type, std::size_t>);
static_assert(count_iterable_array() == 10);
std::cout << "line " << __LINE__ << ": " << count_iterable_array() << "\n";
constexpr iterable_array array{};
auto [v, s] = array;
static_assert(std::is_same_v<decltype(v), std::vector<std::uint32_t>>);
static_assert(std::is_same_v<decltype(s), std::size_t>);
std::cout << "line " << __LINE__ << ": typeid(v).name() " << typeid(v).name() << "\n";
std::cout << "line " << __LINE__ << ": typeid(s).name() " << typeid(s).name() << "\n";
system("pause");
return 0;
}