Skip to content

Commit 298111b

Browse files
committed
:speadboat: [mph] speed up compilation times (binary search)
1 parent 5d5b171 commit 298111b

File tree

2 files changed

+61
-79
lines changed

2 files changed

+61
-79
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,8 @@ constexpr void for_each(auto fn);
247247
> Configuration
248248
249249
```cpp
250-
#define MP 2'0'2 // Current library version (SemVer)
250+
#define MP 2'0'2 // Current library version (SemVer)
251+
#define MP_SIZE 1024 // Max number of meta types (compilation times optimization)
251252
```
252253

253254
---

mp

Lines changed: 59 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
#pragma GCC system_header
1212
#endif
1313

14+
#if not defined(MP_SIZE)
15+
#define MP_SIZE 1024
16+
#endif
17+
1418
/**
1519
* ~~Template~~ Meta-Programming library (https://github.com/boost-ext/mp)
1620
*/
@@ -26,10 +30,13 @@ template<size_t Size> using make_index_sequence =
2630
#else
2731
index_sequence<__integer_pack(Size)...>;
2832
#endif
29-
template<class TRange>
30-
concept range = requires (TRange range) { range.begin(); range.end(); };
3133
} // namespace utility
3234

35+
/**
36+
* Meta info type
37+
*/
38+
enum class info : size_t { };
39+
3340
/**
3441
* Minimal - non-conforming - array optimized for fast compilation-times
3542
*
@@ -65,19 +72,20 @@ template<class T, class... Ts> array(T, Ts...) -> array<T, 1u + sizeof...(Ts)>;
6572
* Minimal - non-conforming - static vector optimized for fast compilation-times
6673
*
6774
* @code
68-
* static_vector v{meta<void>, meta<int>};
75+
* vector v{meta<void>, meta<int>};
6976
* assert(2 == v.size());
7077
* assert(meta<void> == v[0]);
7178
* assert(meta<int> == v[1]);
7279
* @endcode
7380
*/
74-
template<class T, size_t Size>
75-
struct static_vector {
81+
template<class T = info, size_t Size = MP_SIZE>
82+
struct vector {
7683
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; } }
8189
constexpr void push_back(const T& t) { data[size_++] = t; }
8290
constexpr void emplace_back(T&& t) { data[size_++] = static_cast<T&&>(t); }
8391
[[nodiscard]] constexpr auto begin() const { return &data[0]; }
@@ -89,56 +97,38 @@ struct static_vector {
8997
[[nodiscard]] constexpr auto size() const { return size_; }
9098
[[nodiscard]] constexpr auto resize(size_t size) { size_ = size; }
9199
[[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 {
93101
if (size_ != other.size_) { return false; }
94102
for (auto i = 0u; i < size_; ++i) { if (data[i] != other.data[i]) { return false; } }
95103
return true;
96104
}
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 {
98106
return not operator==(other);
99107
}
100108
constexpr void clear() { size_ = {}; }
101109

102110
union { T data[Size]{}; }; // __cpp_trivial_union
103111
size_t size_{};
104112
};
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-
};
130113
template<class T, class... Ts> vector(T, Ts...) -> vector<T, 1u + sizeof...(Ts)>;
131-
#endif
132114

133115
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); };
135117
template<class T> struct meta_info {
136118
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{}; }
142132
};
143133
} // namespace detail
144134

@@ -151,7 +141,7 @@ template<class T> struct meta_info {
151141
* @endcode
152142
*/
153143
template<class T>
154-
inline constexpr info meta = detail::meta_info<T>::id;
144+
inline constexpr info meta = detail::meta_info<T>::type_id;
155145

156146
/**
157147
* Returns underlying type from meta type
@@ -161,7 +151,7 @@ inline constexpr info meta = detail::meta_info<T>::id;
161151
* @endcode
162152
*/
163153
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;
165155

166156
/**
167157
* Applies expression expr to `T<type_of<info>...>`
@@ -197,17 +187,8 @@ inline constexpr auto apply_v = []<size_t... Ns>(utility::index_sequence<Ns...>)
197187
* static_assert(typeid(variant<int>) == typeid(apply_t<variant, [] { return vector{meta<int>}; }>));
198188
* @endcode
199189
*/
200-
#if defined(__clang__) || defined(_MSC_VER)
201190
template<template<class...> class R, auto V>
202191
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
211192

212193
/**
213194
* Invokes function with compile-time info based on run-time info
@@ -229,7 +210,7 @@ constexpr auto invoke(Fn fn, info meta) {
229210
};
230211
}.template operator()<info{Ns}>()...
231212
};
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)>{});
233214
return dispatch[size_t(meta)](fn);
234215
}
235216

@@ -283,16 +264,16 @@ namespace mp::test {
283264
} // namespace mp::test
284265

285266
static_assert(([] {
286-
using mp::test::expect;
267+
using namespace mp::test;
287268

288269
// mp::test
289270
{
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>);
296277
}
297278

298279
// mp::utility::index_sequence
@@ -441,9 +422,9 @@ static_assert(([] {
441422

442423
// mp::detail
443424
{
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);
447428
}
448429

449430
// mp::meta
@@ -458,33 +439,33 @@ static_assert(([] {
458439
// mp::type_of
459440
{
460441
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>>>);
465446

466447
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]>>);
469450
}
470451

471452
// mp::apply
472453
{
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>}; })));
476457
}
477458

478459
// mp::invoke
479460
{
480461
static_assert(mp::invoke([]<mp::info meta> { return meta == mp::meta<int>; }, mp::meta<int>));
481462
static_assert(not mp::invoke([]<mp::info meta> { return meta == mp::meta<void>; }, mp::meta<int>));
482463

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>));
485466

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>)>>);
488469
}
489470

490471
// mp::for_each

0 commit comments

Comments
 (0)