11
11
#pragma GCC system_header
12
12
#endif
13
13
14
+ #if not defined(MP_SIZE)
15
+ #define MP_SIZE 1024
16
+ #endif
17
+
14
18
/**
15
19
* ~~Template~~ Meta-Programming library (https://github.com/boost-ext/mp)
16
20
*/
@@ -26,10 +30,13 @@ template<size_t Size> using make_index_sequence =
26
30
#else
27
31
index_sequence<__integer_pack(Size)...>;
28
32
#endif
29
- template<class TRange>
30
- concept range = requires (TRange range) { range.begin(); range.end(); };
31
33
} // namespace utility
32
34
35
+ /**
36
+ * Meta info type
37
+ */
38
+ enum class info : size_t { };
39
+
33
40
/**
34
41
* Minimal - non-conforming - array optimized for fast compilation-times
35
42
*
@@ -65,19 +72,20 @@ template<class T, class... Ts> array(T, Ts...) -> array<T, 1u + sizeof...(Ts)>;
65
72
* Minimal - non-conforming - static vector optimized for fast compilation-times
66
73
*
67
74
* @code
68
- * static_vector v{meta<void>, meta<int>};
75
+ * vector v{meta<void>, meta<int>};
69
76
* assert(2 == v.size());
70
77
* assert(meta<void> == v[0]);
71
78
* assert(meta<int> == v[1]);
72
79
* @endcode
73
80
*/
74
- template<class T, size_t Size>
75
- struct static_vector {
81
+ template<class T = info , size_t Size = MP_SIZE >
82
+ struct vector {
76
83
using value_type = T;
77
- constexpr static_vector() = default;
78
- constexpr static_vector(size_t size) : size_{size} { }
79
- template<class... Ts> constexpr explicit static_vector(const Ts&... ts) : data{ts...}, size_{sizeof...(ts)} { }
80
- constexpr static_vector(utility::range auto range) { for (const T& t : range) { data[size_++] = t; } }
84
+ constexpr vector() = default;
85
+ constexpr vector(size_t size) : size_{size} { }
86
+ constexpr explicit vector(const auto&... ts) : data{ts...}, size_{sizeof...(ts)} { }
87
+ template<class TRange> requires requires(TRange range) { range.begin(); range.end(); }
88
+ constexpr vector(TRange range) { for (const auto& t : range) { data[size_++] = t; } }
81
89
constexpr void push_back(const T& t) { data[size_++] = t; }
82
90
constexpr void emplace_back(T&& t) { data[size_++] = static_cast<T&&>(t); }
83
91
[[nodiscard]] constexpr auto begin() const { return &data[0]; }
@@ -89,56 +97,38 @@ struct static_vector {
89
97
[[nodiscard]] constexpr auto size() const { return size_; }
90
98
[[nodiscard]] constexpr auto resize(size_t size) { size_ = size; }
91
99
[[nodiscard]] constexpr auto capacity() const { return Size; }
92
- template<size_t size> [[nodiscard]] constexpr auto operator==(const static_vector <T, size>& other) const -> bool {
100
+ template<size_t size> [[nodiscard]] constexpr auto operator==(const vector <T, size>& other) const -> bool {
93
101
if (size_ != other.size_) { return false; }
94
102
for (auto i = 0u; i < size_; ++i) { if (data[i] != other.data[i]) { return false; } }
95
103
return true;
96
104
}
97
- template<size_t size> [[nodiscard]] constexpr auto operator!=(const static_vector <T, size>& other) const -> bool {
105
+ template<size_t size> [[nodiscard]] constexpr auto operator!=(const vector <T, size>& other) const -> bool {
98
106
return not operator==(other);
99
107
}
100
108
constexpr void clear() { size_ = {}; }
101
109
102
110
union { T data[Size]{}; }; // __cpp_trivial_union
103
111
size_t size_{};
104
112
};
105
- template<class T, class... Ts> static_vector(T, Ts...) -> static_vector<T, 1u + sizeof...(Ts)>;
106
-
107
- /**
108
- * Meta info type
109
- */
110
- enum class info : size_t { };
111
-
112
- /**
113
- * Meta info vector
114
- */
115
- #if not defined(MP_SIZE)
116
- #define MP_SIZE 1024
117
- #endif
118
- #if defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201907L)
119
- template<class T = info, size_t Size = MP_SIZE>
120
- using vector = static_vector<T, Size>;
121
- #else
122
- template<class T = info, size_t Size = MP_SIZE>
123
- struct vector : static_vector<T, Size> {
124
- using static_vector<T, Size>::static_vector;
125
- constexpr vector() = default;
126
- constexpr vector(utility::range auto range) {
127
- for (const T& t : range) { static_vector<T, Size>::data[static_vector<T, Size>::size_++] = t; }
128
- }
129
- };
130
113
template<class T, class... Ts> vector(T, Ts...) -> vector<T, 1u + sizeof...(Ts)>;
131
- #endif
132
114
133
115
namespace detail {
134
- template<info> struct meta_id { constexpr auto friend get(meta_id ); };
116
+ template<info> struct meta_type { constexpr auto friend get(meta_type ); };
135
117
template<class T> struct meta_info {
136
118
using value_type = T;
137
- template<info N = info{}> static constexpr auto idx() -> info {
138
- if constexpr (requires { get(meta_id<N>{}); }) { return idx<info{size_t(N) + 1u}>(); } else { return N; }
139
- };
140
- static constexpr info id = idx();
141
- constexpr auto friend get(meta_id<id>) { return meta_info{}; }
119
+ template<size_t left = 0u, size_t right = MP_SIZE - 1u>
120
+ static constexpr auto id() -> size_t {
121
+ if constexpr (left >= right) {
122
+ return left + requires { get(meta_type<info{left}>{}); };
123
+ } else if constexpr (constexpr auto mid = left + (right - left) / 2u;
124
+ requires { get(meta_type<info{mid}>{}); }) {
125
+ return id<mid + 1u, right>();
126
+ } else {
127
+ return id<left, mid - 1u>();
128
+ }
129
+ }
130
+ static constexpr auto type_id = info{id()};
131
+ constexpr auto friend get(meta_type<type_id>) { return meta_info{}; }
142
132
};
143
133
} // namespace detail
144
134
@@ -151,7 +141,7 @@ template<class T> struct meta_info {
151
141
* @endcode
152
142
*/
153
143
template<class T>
154
- inline constexpr info meta = detail::meta_info<T>::id ;
144
+ inline constexpr info meta = detail::meta_info<T>::type_id ;
155
145
156
146
/**
157
147
* Returns underlying type from meta type
@@ -161,7 +151,7 @@ inline constexpr info meta = detail::meta_info<T>::id;
161
151
* @endcode
162
152
*/
163
153
template<info meta>
164
- using type_of = typename decltype(get(detail::meta_id <meta>{}))::value_type;
154
+ using type_of = typename decltype(get(detail::meta_type <meta>{}))::value_type;
165
155
166
156
/**
167
157
* Applies expression expr to `T<type_of<info>...>`
@@ -197,17 +187,8 @@ inline constexpr auto apply_v = []<size_t... Ns>(utility::index_sequence<Ns...>)
197
187
* static_assert(typeid(variant<int>) == typeid(apply_t<variant, [] { return vector{meta<int>}; }>));
198
188
* @endcode
199
189
*/
200
- #if defined(__clang__) || defined(_MSC_VER)
201
190
template<template<class...> class R, auto V>
202
191
using apply_t = decltype(apply<R>([] { return V; }));
203
- #else
204
- namespace detail {
205
- template<template<class...> class R, auto V, size_t... Ns>
206
- using apply_t = R<type_of<V[Ns]>...>;
207
- } // namespace detail
208
- template<template<class...> class R, auto V>
209
- using apply_t = detail::apply_t<R, V, __integer_pack(V.size())...>;
210
- #endif
211
192
212
193
/**
213
194
* Invokes function with compile-time info based on run-time info
@@ -229,7 +210,7 @@ constexpr auto invoke(Fn fn, info meta) {
229
210
};
230
211
}.template operator()<info{Ns}>()...
231
212
};
232
- }(utility::make_index_sequence<size_t(detail::meta_info<decltype(tag)>::id )>{});
213
+ }(utility::make_index_sequence<size_t(detail::meta_info<decltype(tag)>::type_id )>{});
233
214
return dispatch[size_t(meta)](fn);
234
215
}
235
216
@@ -283,16 +264,16 @@ namespace mp::test {
283
264
} // namespace mp::test
284
265
285
266
static_assert(([] {
286
- using mp::test::expect ;
267
+ using namespace mp::test;
287
268
288
269
// mp::test
289
270
{
290
- static_assert(not mp::test:: is_same_v<int, void>);
291
- static_assert(not mp::test:: is_same_v<void, int>);
292
- static_assert(not mp::test:: is_same_v<void*, int>);
293
- static_assert(not mp::test:: is_same_v<int, const int>);
294
- static_assert(mp::test:: is_same_v<void, void>);
295
- static_assert(mp::test:: is_same_v<int, int>);
271
+ static_assert(not is_same_v<int, void>);
272
+ static_assert(not is_same_v<void, int>);
273
+ static_assert(not is_same_v<void*, int>);
274
+ static_assert(not is_same_v<int, const int>);
275
+ static_assert(is_same_v<void, void>);
276
+ static_assert(is_same_v<int, int>);
296
277
}
297
278
298
279
// mp::utility::index_sequence
@@ -441,9 +422,9 @@ static_assert(([] {
441
422
442
423
// mp::detail
443
424
{
444
- static_assert(mp::detail::meta_info<int>::id == mp::detail::meta_info<int>::id );
445
- static_assert(mp::detail::meta_info<int>::id != mp::detail::meta_info<void>::id );
446
- static_assert(mp::detail::meta_info<void>::id == mp::detail::meta_info<void>::id );
425
+ static_assert(mp::detail::meta_info<int>::type_id == mp::detail::meta_info<int>::type_id );
426
+ static_assert(mp::detail::meta_info<int>::type_id != mp::detail::meta_info<void>::type_id );
427
+ static_assert(mp::detail::meta_info<void>::type_id == mp::detail::meta_info<void>::type_id );
447
428
}
448
429
449
430
// mp::meta
@@ -458,33 +439,33 @@ static_assert(([] {
458
439
// mp::type_of
459
440
{
460
441
enum class e : int { };
461
- static_assert(mp::test:: is_same_v<void, mp::type_of<mp::meta<void>>>);
462
- static_assert(mp::test:: is_same_v<const int, mp::type_of<mp::meta<const int>>>);
463
- static_assert(mp::test:: is_same_v<const void*, mp::type_of<mp::meta<const void*>>>);
464
- static_assert(mp::test:: is_same_v<e, mp::type_of<mp::meta<e>>>);
442
+ static_assert(is_same_v<void, mp::type_of<mp::meta<void>>>);
443
+ static_assert(is_same_v<const int, mp::type_of<mp::meta<const int>>>);
444
+ static_assert(is_same_v<const void*, mp::type_of<mp::meta<const void*>>>);
445
+ static_assert(is_same_v<e, mp::type_of<mp::meta<e>>>);
465
446
466
447
constexpr mp::vector v{mp::meta<int>, mp::meta<e>};
467
- static_assert(mp::test:: is_same_v<int, mp::type_of<v[0]>>);
468
- static_assert(mp::test:: is_same_v<e, mp::type_of<v[1]>>);
448
+ static_assert(is_same_v<int, mp::type_of<v[0]>>);
449
+ static_assert(is_same_v<e, mp::type_of<v[1]>>);
469
450
}
470
451
471
452
// mp::apply
472
453
{
473
- static_assert([](mp::test:: type_list<>){ return true; }(mp::apply<mp::test:: type_list>([] { return mp::vector<mp::info, 1>{}; })));
474
- static_assert([](mp::test:: type_list<int>){ return true; }(mp::apply<mp::test:: type_list>([] { return mp::vector{mp::meta<int>}; })));
475
- static_assert([](mp::test:: type_list<void, void>){ return true; }(mp::apply<mp::test:: type_list>([] { return mp::vector{mp::meta<void>, mp::meta<void>}; })));
454
+ static_assert([](type_list<>){ return true; }(mp::apply<type_list>([] { return mp::vector<mp::info, 1>{}; })));
455
+ static_assert([](type_list<int>){ return true; }(mp::apply<type_list>([] { return mp::vector{mp::meta<int>}; })));
456
+ static_assert([](type_list<void, void>){ return true; }(mp::apply<type_list>([] { return mp::vector{mp::meta<void>, mp::meta<void>}; })));
476
457
}
477
458
478
459
// mp::invoke
479
460
{
480
461
static_assert(mp::invoke([]<mp::info meta> { return meta == mp::meta<int>; }, mp::meta<int>));
481
462
static_assert(not mp::invoke([]<mp::info meta> { return meta == mp::meta<void>; }, mp::meta<int>));
482
463
483
- static_assert(not mp::invoke<mp::test:: is_const>(mp::meta<int>));
484
- static_assert(mp::invoke<mp::test:: is_const>(mp::meta<const int>));
464
+ static_assert(not mp::invoke<is_const>(mp::meta<int>));
465
+ static_assert(mp::invoke<is_const>(mp::meta<const int>));
485
466
486
- static_assert(mp::test:: is_same_v<const int, mp::type_of<mp::invoke<mp::test:: add_const>(mp::meta<int>)>>);
487
- static_assert(mp::test:: is_same_v<const int, mp::type_of<mp::invoke<mp::test:: add_const>(mp::meta<const int>)>>);
467
+ static_assert(is_same_v<const int, mp::type_of<mp::invoke<add_const>(mp::meta<int>)>>);
468
+ static_assert(is_same_v<const int, mp::type_of<mp::invoke<add_const>(mp::meta<const int>)>>);
488
469
}
489
470
490
471
// mp::for_each
0 commit comments