@auto_js/utility 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CMakeLists.txt +6 -1
- package/_module.cc +1 -0
- package/assertions.cc +20 -22
- package/container/mutable_priority_queue.cc +1 -4
- package/container/sealed_map.cc +7 -11
- package/container/segmented_priority_queue.cc +5 -11
- package/container/tinker_queue.cc +3 -6
- package/functional/bind.cc +3 -4
- package/functional/elide.cc +1 -3
- package/functional/flat_tuple.cc +1 -2
- package/functional/function_constant.cc +1 -3
- package/functional/function_ref.cc +32 -5
- package/functional/functional.cc +1 -4
- package/functional/regular_return.cc +1 -3
- package/include/auto_js/export_tag.h +17 -0
- package/include/auto_js/gcc_abi_tag.h +6 -0
- package/memory/autorelease_pool.cc +1 -4
- package/memory/comparator.cc +1 -2
- package/memory/memory.cc +1 -5
- package/memory/noinit_allocator.cc +1 -4
- package/meta/algorithm.cc +11 -4
- package/package.json +1 -1
- package/platform/lockable.cc +7 -12
- package/platform/stop_token.cc +13 -14
- package/platform/timer.cc +1 -11
- package/platform/timer.h.cc +1 -4
- package/type_traits/function_traits.cc +1 -3
- package/type_traits/transform.cc +1 -2
- package/type_traits/type_of.cc +1 -2
- package/type_traits/type_pack.cc +1 -3
- package/utility/constant_wrapper.cc +1 -2
- package/utility/covariant_value.cc +3 -5
- package/utility/facade.cc +24 -20
- package/utility/hash.cc +7 -12
- package/utility/ranges.cc +11 -0
- package/utility/string.cc +21 -37
- package/utility/utility.cc +35 -10
- package/utility/variant.cc +3 -6
package/CMakeLists.txt
CHANGED
|
@@ -6,7 +6,6 @@ target_include_directories(utility_js PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/includ
|
|
|
6
6
|
|
|
7
7
|
target_sources(utility_js
|
|
8
8
|
PRIVATE
|
|
9
|
-
assertions.cc
|
|
10
9
|
platform/timer.cc
|
|
11
10
|
PUBLIC FILE_SET CXX_MODULES FILES
|
|
12
11
|
_module.cc
|
|
@@ -43,3 +42,9 @@ target_sources(utility_js
|
|
|
43
42
|
utility/utility.cc
|
|
44
43
|
utility/variant.cc
|
|
45
44
|
)
|
|
45
|
+
if(CMAKE_BUILD_TYPE STREQUAL Debug)
|
|
46
|
+
target_sources(utility_js
|
|
47
|
+
PRIVATE
|
|
48
|
+
assertions.cc
|
|
49
|
+
)
|
|
50
|
+
endif()
|
package/_module.cc
CHANGED
|
@@ -4,6 +4,7 @@ export import :container.sealed_map;
|
|
|
4
4
|
export import :container.segmented_priority_queue;
|
|
5
5
|
export import :container.tinker_queue;
|
|
6
6
|
export import :functional;
|
|
7
|
+
export import :functional.flat_tuple;
|
|
7
8
|
export import :memory;
|
|
8
9
|
export import :meta.algorithm;
|
|
9
10
|
export import :platform.lockable;
|
package/assertions.cc
CHANGED
|
@@ -1,32 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
#include <type_traits>
|
|
1
|
+
import std;
|
|
3
2
|
import util;
|
|
4
3
|
|
|
5
4
|
constexpr auto assert_strings_equal(auto... strings) {
|
|
6
|
-
const auto [... left ] =
|
|
7
|
-
const auto [... right ] =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
...)
|
|
16
|
-
);
|
|
5
|
+
const auto [... left ] = std::tuple{std::basic_string_view{strings}...};
|
|
6
|
+
const auto [... right ] = std::tuple{std::basic_string_view{strings}...};
|
|
7
|
+
(..., ([ = ](auto left) -> void {
|
|
8
|
+
using char_type = decltype(left)::value_type;
|
|
9
|
+
// NOLINTNEXTLINE(modernize-type-traits)
|
|
10
|
+
if ((... || (left != util::transcode_string<char_type>(right)))) {
|
|
11
|
+
std::unreachable();
|
|
12
|
+
}
|
|
13
|
+
}(left)));
|
|
17
14
|
}
|
|
18
15
|
|
|
19
|
-
[
|
|
16
|
+
static_assert([]() -> int {
|
|
20
17
|
// https://en.cppreference.com/w/cpp/language/string_literal.html
|
|
21
18
|
|
|
22
19
|
// Quick check of interpolation matrix
|
|
23
|
-
assert_strings_equal(
|
|
24
|
-
assert_strings_equal(
|
|
20
|
+
assert_strings_equal(u8"💖", u"💖");
|
|
21
|
+
assert_strings_equal("wow", u8"wow", u"wow", U"wow");
|
|
22
|
+
assert_strings_equal(std::basic_string_view{"\x00", 1}, std::basic_string_view{u8"\x00", 1}, std::basic_string_view{u"\x00", 1}, std::basic_string_view{U"\x00", 1});
|
|
25
23
|
|
|
26
24
|
// Unpaired utf-16 surrogates
|
|
27
|
-
constexpr auto one_high_surrogate =
|
|
28
|
-
static_assert(one_high_surrogate == util::
|
|
29
|
-
constexpr auto two_high_surrogate =
|
|
30
|
-
static_assert(two_high_surrogate == util::
|
|
31
|
-
return
|
|
32
|
-
}();
|
|
25
|
+
constexpr auto one_high_surrogate = std::basic_string_view{u"\xd83d"};
|
|
26
|
+
static_assert(one_high_surrogate == util::transcode_string<char16_t>(one_high_surrogate));
|
|
27
|
+
constexpr auto two_high_surrogate = std::basic_string_view{u"\xd83d\xd83d"};
|
|
28
|
+
static_assert(two_high_surrogate == util::transcode_string<char16_t>(two_high_surrogate));
|
|
29
|
+
return true;
|
|
30
|
+
}());
|
package/container/sealed_map.cc
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
module;
|
|
2
|
-
#include <algorithm>
|
|
3
2
|
#include <concepts>
|
|
4
|
-
#include <format>
|
|
5
|
-
#include <ranges>
|
|
6
|
-
#include <type_traits>
|
|
7
|
-
#include <utility>
|
|
8
3
|
export module util:container.sealed_map;
|
|
9
4
|
import :functional;
|
|
5
|
+
import std;
|
|
10
6
|
|
|
11
7
|
namespace util {
|
|
12
8
|
|
|
13
9
|
struct sorted_equivalent_t {};
|
|
14
10
|
|
|
15
|
-
export template <class Key, class Type, size_t Size>
|
|
11
|
+
export template <class Key, class Type, std::size_t Size>
|
|
16
12
|
class sealed_map {
|
|
17
13
|
public:
|
|
18
14
|
using key_type = Key;
|
|
@@ -22,7 +18,7 @@ class sealed_map {
|
|
|
22
18
|
private:
|
|
23
19
|
// Holder for consteval'd key into the map
|
|
24
20
|
struct key_for {
|
|
25
|
-
using value_type = size_t;
|
|
21
|
+
using value_type = std::size_t;
|
|
26
22
|
constexpr key_for() :
|
|
27
23
|
index_{std::numeric_limits<value_type>::max()} {}
|
|
28
24
|
explicit constexpr key_for(auto index) :
|
|
@@ -32,7 +28,7 @@ class sealed_map {
|
|
|
32
28
|
explicit constexpr operator bool() const { return index_ != std::numeric_limits<value_type>::max(); }
|
|
33
29
|
|
|
34
30
|
private:
|
|
35
|
-
size_t index_;
|
|
31
|
+
std::size_t index_;
|
|
36
32
|
};
|
|
37
33
|
|
|
38
34
|
// Check for duplicates
|
|
@@ -71,9 +67,9 @@ class sealed_map {
|
|
|
71
67
|
util::elide{[ & ]() -> container_type {
|
|
72
68
|
// Sort without invoking `operator()=`, which might not exist on the value type
|
|
73
69
|
auto entries = std::array<value_type, Size>{std::move(pairs)...};
|
|
74
|
-
auto indices = std::array<size_t, Size>{};
|
|
75
|
-
std::ranges::copy(std::ranges::
|
|
76
|
-
const auto projection = [ & ](size_t ii) -> const auto& { return entries.at(ii).first; };
|
|
70
|
+
auto indices = std::array<std::size_t, Size>{};
|
|
71
|
+
std::ranges::copy(std::ranges::views::iota(std::size_t{0}, Size), indices.begin());
|
|
72
|
+
const auto projection = [ & ](std::size_t ii) -> const auto& { return entries.at(ii).first; };
|
|
77
73
|
std::ranges::sort(indices, std::less{}, projection);
|
|
78
74
|
const auto [... sorted_indices ] = indices;
|
|
79
75
|
return {value_type(std::move(entries.at(sorted_indices)))...};
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
module;
|
|
2
|
-
#include <algorithm>
|
|
3
|
-
#include <array>
|
|
4
|
-
#include <functional>
|
|
5
|
-
#include <iterator>
|
|
6
|
-
#include <span>
|
|
7
|
-
#include <utility>
|
|
8
1
|
export module util:container.segmented_priority_queue;
|
|
2
|
+
import std;
|
|
9
3
|
|
|
10
4
|
namespace util {
|
|
11
5
|
|
|
@@ -25,7 +19,7 @@ class ratchet_span : public std::span<Type> {
|
|
|
25
19
|
};
|
|
26
20
|
|
|
27
21
|
// N number of queues, which tracks which ones currently may have elements
|
|
28
|
-
export template <class Queue, size_t Size>
|
|
22
|
+
export template <class Queue, std::size_t Size>
|
|
29
23
|
class segmented_priority_queue {
|
|
30
24
|
public:
|
|
31
25
|
using container_type = Queue;
|
|
@@ -34,7 +28,7 @@ class segmented_priority_queue {
|
|
|
34
28
|
|
|
35
29
|
[[nodiscard]] auto containers() const -> std::span<const container_type> { return not_empty_; }
|
|
36
30
|
[[nodiscard]] auto empty() const -> bool { return std::ranges::all_of(containers(), &Queue::empty); }
|
|
37
|
-
[[nodiscard]] auto size() const -> size_t { return std::ranges::fold_left(containers(), 0UZ, std::plus{}, &Queue::size); }
|
|
31
|
+
[[nodiscard]] auto size() const -> std::size_t { return std::ranges::fold_left(containers(), 0UZ, std::plus{}, &Queue::size); }
|
|
38
32
|
auto at(unsigned priority) -> container_type&;
|
|
39
33
|
auto at(unsigned priority) const -> const container_type& { return queues_.at(priority); }
|
|
40
34
|
auto containers() -> std::span<container_type> { return not_empty_; }
|
|
@@ -79,7 +73,7 @@ auto ratchet_span<Type>::make_iterator(auto it) -> iterator {
|
|
|
79
73
|
}
|
|
80
74
|
|
|
81
75
|
// `segmented_priority_queue`
|
|
82
|
-
template <class Queue, size_t Size>
|
|
76
|
+
template <class Queue, std::size_t Size>
|
|
83
77
|
auto segmented_priority_queue<Queue, Size>::at(unsigned priority) -> container_type& {
|
|
84
78
|
// We don't know what you're about to do with it, so assume that it will gain an element
|
|
85
79
|
auto& queue = queues_.at(priority);
|
|
@@ -87,7 +81,7 @@ auto segmented_priority_queue<Queue, Size>::at(unsigned priority) -> container_t
|
|
|
87
81
|
return queue;
|
|
88
82
|
}
|
|
89
83
|
|
|
90
|
-
template <class Queue, size_t Size>
|
|
84
|
+
template <class Queue, std::size_t Size>
|
|
91
85
|
auto segmented_priority_queue<Queue, Size>::pop() -> void {
|
|
92
86
|
for (auto& queue : not_empty_) {
|
|
93
87
|
if (queue.empty()) {
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
module;
|
|
2
|
-
#include <algorithm>
|
|
3
2
|
#include <cassert>
|
|
4
|
-
#include <concepts>
|
|
5
|
-
#include <deque>
|
|
6
|
-
#include <utility>
|
|
7
3
|
export module util:container.tinker_queue;
|
|
4
|
+
import std;
|
|
8
5
|
|
|
9
6
|
namespace util {
|
|
10
7
|
|
|
@@ -19,7 +16,7 @@ class tinker_queue {
|
|
|
19
16
|
using value_type = Value;
|
|
20
17
|
|
|
21
18
|
[[nodiscard]] auto empty() const -> bool { return size() == 0; }
|
|
22
|
-
[[nodiscard]] auto size() const -> size_t { return queue_.size() - empty_middle_values_; }
|
|
19
|
+
[[nodiscard]] auto size() const -> std::size_t { return queue_.size() - empty_middle_values_; }
|
|
23
20
|
// nb: You don't want a `clear` method here because you want tasks to be destroyed in the order
|
|
24
21
|
// they were added
|
|
25
22
|
auto emplace(auto&&... args) -> void;
|
|
@@ -29,7 +26,7 @@ class tinker_queue {
|
|
|
29
26
|
|
|
30
27
|
private:
|
|
31
28
|
container_type queue_;
|
|
32
|
-
size_t empty_middle_values_{};
|
|
29
|
+
std::size_t empty_middle_values_{};
|
|
33
30
|
};
|
|
34
31
|
|
|
35
32
|
// ---
|
package/functional/bind.cc
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
module;
|
|
2
2
|
#include "auto_js/no_unique_address.h"
|
|
3
|
-
#include <type_traits>
|
|
4
|
-
#include <utility>
|
|
5
3
|
export module util:functional.bind;
|
|
6
4
|
import :functional.flat_tuple;
|
|
7
|
-
import :type_traits;
|
|
8
5
|
import :utility;
|
|
6
|
+
import std;
|
|
9
7
|
|
|
10
8
|
namespace util {
|
|
11
9
|
|
|
@@ -83,7 +81,7 @@ class bind_explicit<Invocable, auto(Args...) noexcept(Nx)->Result, Bound...> : p
|
|
|
83
81
|
|
|
84
82
|
using try_cvref_type = apply_cvref_t<ensure_reference_t<invocable_type_t<Invocable>>, Invocable>;
|
|
85
83
|
using cvref_type =
|
|
86
|
-
std::conditional_t<std::is_invocable_v<try_cvref_type, apply_cvref_t<try_cvref_type, Bound
|
|
84
|
+
std::conditional_t<std::is_invocable_v<try_cvref_type, apply_cvref_t<try_cvref_type, Bound>..., Args...>, try_cvref_type, bind_explicit&>;
|
|
87
85
|
using this_type = apply_cvref_t<cvref_type, bind_explicit>;
|
|
88
86
|
constexpr static auto invoke_as_mutable = std::is_same_v<this_type, bind_explicit&>;
|
|
89
87
|
constexpr static auto invoke_as_forward = !invoke_as_mutable;
|
|
@@ -148,4 +146,5 @@ template <class Invocable, class... Bound>
|
|
|
148
146
|
class bind<Invocable, Bound...> : public bind_explicit_params_t<Invocable, Bound...> {
|
|
149
147
|
using bind_explicit_params_t<Invocable, Bound...>::bind_explicit_params_t;
|
|
150
148
|
};
|
|
149
|
+
|
|
151
150
|
} // namespace util
|
package/functional/elide.cc
CHANGED
package/functional/flat_tuple.cc
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
module;
|
|
2
|
-
#include <concepts>
|
|
3
|
-
#include <type_traits>
|
|
4
|
-
#include <utility>
|
|
5
1
|
export module util:functional.function_ref;
|
|
6
2
|
import :functional.elide;
|
|
7
3
|
import :type_traits;
|
|
4
|
+
import std;
|
|
8
5
|
|
|
9
6
|
namespace util {
|
|
10
7
|
|
|
@@ -27,7 +24,11 @@ class function_ref<auto(Args...) noexcept(Nx)->Result> {
|
|
|
27
24
|
|
|
28
25
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
|
29
26
|
constexpr function_ref(signature_type* function) :
|
|
30
|
-
|
|
27
|
+
invoke_{[](void* ptr, Args... args) noexcept(Nx) -> Result {
|
|
28
|
+
auto& fn = *reinterpret_cast<signature_type*>(ptr);
|
|
29
|
+
return fn(std::forward<Args>(args)...);
|
|
30
|
+
}},
|
|
31
|
+
ptr_{reinterpret_cast<void*>(function)} {}
|
|
31
32
|
|
|
32
33
|
template <std::invocable<Args...> Object>
|
|
33
34
|
requires(type<Object> != type<function_ref>)
|
|
@@ -54,6 +55,17 @@ class function_ref<auto(Args...) noexcept(Nx)->Result> {
|
|
|
54
55
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
|
55
56
|
ptr_{const_cast<void*>(static_cast<const void*>(&bound))} {}
|
|
56
57
|
|
|
58
|
+
template <class Object, std::invocable<Object*, Args...> Function>
|
|
59
|
+
requires std::is_empty_v<Function>
|
|
60
|
+
constexpr explicit function_ref(Function /*function*/, Object* bound) :
|
|
61
|
+
invoke_{[](void* ptr, Args... args) noexcept(Nx) -> Result {
|
|
62
|
+
auto* object = static_cast<Object*>(ptr);
|
|
63
|
+
constexpr auto function = Function{};
|
|
64
|
+
return function(object, std::forward<Args>(args)...);
|
|
65
|
+
}},
|
|
66
|
+
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
|
67
|
+
ptr_{const_cast<void*>(static_cast<const void*>(bound))} {}
|
|
68
|
+
|
|
57
69
|
constexpr auto operator()(Args... args) const noexcept(Nx) -> Result {
|
|
58
70
|
return invoke_(ptr_, std::forward<Args>(args)...);
|
|
59
71
|
}
|
|
@@ -65,4 +77,19 @@ class function_ref<auto(Args...) noexcept(Nx)->Result> {
|
|
|
65
77
|
void* ptr_;
|
|
66
78
|
};
|
|
67
79
|
|
|
80
|
+
// Deduction guide helper for bound object ref
|
|
81
|
+
template <class Signature>
|
|
82
|
+
struct function_ref_deduction_guide;
|
|
83
|
+
|
|
84
|
+
template <class Result, bool Nx, class Object, class... Args>
|
|
85
|
+
struct function_ref_deduction_guide<auto(Object, Args...) noexcept(Nx)->Result>
|
|
86
|
+
: std::type_identity<auto(Args...) noexcept(Nx)->Result> {};
|
|
87
|
+
|
|
88
|
+
export template <class Function>
|
|
89
|
+
function_ref(Function, auto&&)
|
|
90
|
+
-> function_ref<typename function_ref_deduction_guide<function_signature_t<Function>>::type>;
|
|
91
|
+
|
|
92
|
+
export template <class Function>
|
|
93
|
+
function_ref(Function) -> function_ref<function_signature_t<Function>>;
|
|
94
|
+
|
|
68
95
|
} // namespace util
|
package/functional/functional.cc
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
module;
|
|
2
|
-
#include <functional>
|
|
3
|
-
#include <utility>
|
|
4
1
|
export module util:functional;
|
|
5
2
|
export import :functional.bind;
|
|
6
3
|
export import :functional.elide;
|
|
7
4
|
export import :functional.function_constant;
|
|
8
5
|
export import :functional.function_ref;
|
|
9
6
|
export import :functional.regular_return;
|
|
10
|
-
import
|
|
7
|
+
import std;
|
|
11
8
|
|
|
12
9
|
namespace util {
|
|
13
10
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#if EXPORT_IS_EXPORT
|
|
2
|
+
|
|
3
|
+
#if _WIN64
|
|
4
|
+
#define EXPORT __declspec(dllexport)
|
|
5
|
+
#else
|
|
6
|
+
#define EXPORT __attribute__((visibility("default")))
|
|
7
|
+
#endif
|
|
8
|
+
|
|
9
|
+
#else
|
|
10
|
+
|
|
11
|
+
#if _WIN64
|
|
12
|
+
#define EXPORT __declspec(dllimport)
|
|
13
|
+
#else
|
|
14
|
+
#define EXPORT
|
|
15
|
+
#endif
|
|
16
|
+
|
|
17
|
+
#endif
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
module;
|
|
2
2
|
#include "auto_js/no_unique_address.h"
|
|
3
|
-
#include <algorithm>
|
|
4
3
|
#include <cassert>
|
|
5
|
-
#include <memory>
|
|
6
|
-
#include <utility>
|
|
7
|
-
#include <vector>
|
|
8
4
|
export module util:memory.autorelease_pool;
|
|
9
5
|
import :memory.comparator;
|
|
10
6
|
import :utility;
|
|
7
|
+
import std;
|
|
11
8
|
|
|
12
9
|
namespace util {
|
|
13
10
|
|
package/memory/comparator.cc
CHANGED
package/memory/memory.cc
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
module;
|
|
2
|
-
#include <concepts>
|
|
3
|
-
#include <functional>
|
|
4
|
-
#include <memory>
|
|
5
|
-
#include <type_traits>
|
|
6
1
|
export module util:memory;
|
|
7
2
|
export import :memory.autorelease_pool;
|
|
8
3
|
export import :memory.comparator;
|
|
9
4
|
export import :memory.noinit_allocator;
|
|
5
|
+
import std;
|
|
10
6
|
|
|
11
7
|
namespace util {
|
|
12
8
|
|
package/meta/algorithm.cc
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
module;
|
|
2
|
-
#include <type_traits>
|
|
3
1
|
export module util:meta.algorithm;
|
|
4
2
|
import :functional;
|
|
5
|
-
import
|
|
3
|
+
import std;
|
|
6
4
|
|
|
7
5
|
namespace util {
|
|
8
6
|
|
|
@@ -10,11 +8,20 @@ namespace util {
|
|
|
10
8
|
export constexpr auto make_type_pack = util::overloaded{
|
|
11
9
|
// nb: Prevent `make_type_pack{type_pack_of{...}}` from turning into a mess of hidden types
|
|
12
10
|
[]<class... Types>(type_pack_of<Types...> pack) consteval -> auto { return pack; },
|
|
13
|
-
[]<template <class
|
|
11
|
+
[]<template <class...> class Pack, class... Types>(std::type_identity<Pack<Types...>> /*type*/) consteval -> auto {
|
|
14
12
|
return type_pack_of{type<Types>...};
|
|
15
13
|
},
|
|
16
14
|
};
|
|
17
15
|
|
|
16
|
+
// Resolves a `Something<T...>` from `SomethingElse<T...>`
|
|
17
|
+
export template <template <class...> class Into>
|
|
18
|
+
constexpr auto spread_type_pack = util::overloaded{
|
|
19
|
+
[]<class... Hidden>(type_pack_of<Hidden...> /*pack*/) consteval -> auto { return type<Into<typename Hidden::type...>>; },
|
|
20
|
+
[]<template <class...> class Pack, class... Types>(std::type_identity<Pack<Types...>> /*type*/) consteval -> auto {
|
|
21
|
+
return type<Into<Types...>>;
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
18
25
|
// Concatenate 0..N `util::type_packs` together
|
|
19
26
|
export constexpr auto pack_concat = util::overloaded{
|
|
20
27
|
[]() consteval -> auto { return type_pack{}; },
|
package/package.json
CHANGED
package/platform/lockable.cc
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
module;
|
|
2
2
|
#include "auto_js/no_unique_address.h"
|
|
3
3
|
#include <cassert>
|
|
4
|
-
#include <concepts>
|
|
5
|
-
#include <condition_variable>
|
|
6
|
-
#include <functional>
|
|
7
|
-
#include <mutex>
|
|
8
|
-
#include <shared_mutex>
|
|
9
|
-
#include <stop_token>
|
|
10
|
-
#include <utility>
|
|
11
|
-
#include <variant>
|
|
12
4
|
export module util:platform.lockable;
|
|
13
|
-
import :type_traits;
|
|
14
5
|
import :utility;
|
|
6
|
+
import std;
|
|
15
7
|
|
|
16
8
|
namespace util {
|
|
17
9
|
|
|
@@ -237,8 +229,8 @@ struct lockable_traits {
|
|
|
237
229
|
bool shared{};
|
|
238
230
|
};
|
|
239
231
|
|
|
240
|
-
|
|
241
|
-
|
|
232
|
+
template <class Resource, lockable_traits Traits = {}>
|
|
233
|
+
constexpr auto make_lockable_traits = []() consteval {
|
|
242
234
|
using mutex_type = type_t<[]() {
|
|
243
235
|
if constexpr (Traits.shared) {
|
|
244
236
|
return type<std::shared_mutex>;
|
|
@@ -256,6 +248,9 @@ using lockable_with = type_t<[]() consteval {
|
|
|
256
248
|
}
|
|
257
249
|
}()>;
|
|
258
250
|
return type<lockable<Resource, mutex_type, cv_type>>;
|
|
259
|
-
}
|
|
251
|
+
};
|
|
252
|
+
export template <class Resource, lockable_traits Traits = {}>
|
|
253
|
+
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124953
|
|
254
|
+
using lockable_with = decltype(make_lockable_traits<Resource, Traits>())::type;
|
|
260
255
|
|
|
261
256
|
} // namespace util
|
package/platform/stop_token.cc
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
|
-
module;
|
|
2
|
-
#include <stop_token>
|
|
3
|
-
#include <utility>
|
|
4
1
|
export module util:platform.stop_token;
|
|
5
2
|
import :functional;
|
|
6
|
-
import
|
|
3
|
+
import std;
|
|
7
4
|
|
|
8
5
|
namespace util {
|
|
9
6
|
|
|
10
7
|
// Combine multiple `std::stop_token`s into one `std::stop_token` that is stopped when any of the
|
|
11
8
|
// source tokens is stopped.
|
|
12
|
-
export template <size_t Size>
|
|
9
|
+
export template <std::size_t Size>
|
|
13
10
|
class composite_stop_token : private std::stop_source, public std::stop_token {
|
|
14
11
|
private:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
12
|
+
class bound_stop_callback {
|
|
13
|
+
public:
|
|
14
|
+
explicit bound_stop_callback(std::stop_source source) : stop_source_{std::move(source)} {}
|
|
15
|
+
auto operator()() { stop_source_.request_stop(); }
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
private:
|
|
18
|
+
std::stop_source stop_source_;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
using stop_callback_type = std::stop_callback<bound_stop_callback>;
|
|
23
22
|
using callback_pack_type = std::array<stop_callback_type, Size>;
|
|
24
23
|
|
|
25
24
|
public:
|
|
@@ -76,13 +75,13 @@ class composite_stop_token : private std::stop_source, public std::stop_token {
|
|
|
76
75
|
case 0:
|
|
77
76
|
case 1:
|
|
78
77
|
{
|
|
79
|
-
auto callback =
|
|
78
|
+
auto callback = bound_stop_callback{std::stop_source{}};
|
|
80
79
|
return {stop_callback_type{(util::unused(tokens), std::stop_token{}), callback}...};
|
|
81
80
|
}
|
|
82
81
|
// Make callback pack
|
|
83
82
|
default:
|
|
84
83
|
{
|
|
85
|
-
auto callback =
|
|
84
|
+
auto callback = bound_stop_callback{std::move(static_cast<std::stop_source&>(*this))};
|
|
86
85
|
return {stop_callback_type{std::forward<decltype(tokens)>(tokens), callback}...};
|
|
87
86
|
}
|
|
88
87
|
}
|
package/platform/timer.cc
CHANGED
|
@@ -1,18 +1,8 @@
|
|
|
1
|
-
module;
|
|
2
|
-
#include <algorithm>
|
|
3
|
-
#include <array>
|
|
4
|
-
#include <chrono>
|
|
5
|
-
#include <functional>
|
|
6
|
-
#include <memory>
|
|
7
|
-
#include <ranges>
|
|
8
|
-
#include <stop_token>
|
|
9
|
-
#include <thread>
|
|
10
|
-
#include <utility>
|
|
11
|
-
#include <vector>
|
|
12
1
|
module util;
|
|
13
2
|
import :functional;
|
|
14
3
|
import :platform.lockable;
|
|
15
4
|
import :platform.timer;
|
|
5
|
+
import std;
|
|
16
6
|
|
|
17
7
|
namespace util {
|
|
18
8
|
|
package/platform/timer.h.cc
CHANGED
package/type_traits/transform.cc
CHANGED
package/type_traits/type_of.cc
CHANGED
package/type_traits/type_pack.cc
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
module;
|
|
2
|
-
#include <utility>
|
|
3
|
-
#include <variant>
|
|
4
1
|
export module util:utility.covariant_value;
|
|
5
|
-
import :utility.facade;
|
|
6
2
|
import :type_traits;
|
|
3
|
+
import :utility.facade;
|
|
4
|
+
import std;
|
|
7
5
|
|
|
8
6
|
namespace util {
|
|
9
7
|
|
|
@@ -17,7 +15,7 @@ class covariant_value : public pointer_facade {
|
|
|
17
15
|
constexpr explicit covariant_value(Derived value) :
|
|
18
16
|
value_{std::move(value)} {}
|
|
19
17
|
|
|
20
|
-
constexpr auto operator*(this auto& self) -> auto& {
|
|
18
|
+
constexpr auto operator*(this auto& self) noexcept -> auto& {
|
|
21
19
|
using reference_type = util::apply_cvref_t<decltype(self), Type>;
|
|
22
20
|
if (self.value_.index() == std::variant_npos) {
|
|
23
21
|
std::unreachable();
|
package/utility/facade.cc
CHANGED
|
@@ -1,35 +1,39 @@
|
|
|
1
|
-
module;
|
|
2
|
-
#include <memory>
|
|
3
|
-
#include <type_traits>
|
|
4
|
-
#include <utility>
|
|
5
1
|
export module util:utility.facade;
|
|
2
|
+
import std;
|
|
6
3
|
|
|
7
4
|
namespace util {
|
|
8
5
|
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
class addition_facade {
|
|
6
|
+
// Implements `Type++` via `++Type`
|
|
7
|
+
export class incrementable_facade {
|
|
12
8
|
public:
|
|
13
|
-
using difference_type =
|
|
14
|
-
|
|
15
|
-
// ++Type
|
|
16
|
-
auto operator++(this auto& self) -> auto& { return self += 1; }
|
|
9
|
+
using difference_type = int;
|
|
17
10
|
|
|
18
11
|
// Type++
|
|
19
|
-
auto operator++(this auto& self, int) {
|
|
12
|
+
constexpr auto operator++(this auto& self, int) {
|
|
20
13
|
auto result = self;
|
|
21
14
|
++self;
|
|
22
15
|
return result;
|
|
23
16
|
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Implements addition operators via `operator+=()`
|
|
20
|
+
export template <class difference_type_>
|
|
21
|
+
class addition_facade : public incrementable_facade {
|
|
22
|
+
public:
|
|
23
|
+
using incrementable_facade::operator++;
|
|
24
|
+
using difference_type = difference_type_;
|
|
25
|
+
|
|
26
|
+
// ++Type
|
|
27
|
+
constexpr auto operator++(this auto& self) -> auto& { return self += 1; }
|
|
24
28
|
|
|
25
29
|
// Type + difference_type
|
|
26
|
-
auto operator+(this const auto& self, difference_type offset) {
|
|
30
|
+
constexpr auto operator+(this const auto& self, difference_type offset) {
|
|
27
31
|
auto result = self;
|
|
28
32
|
return result += offset;
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
// difference_type + Type
|
|
32
|
-
friend auto operator+(difference_type left, const auto& right) {
|
|
36
|
+
constexpr friend auto operator+(difference_type left, const auto& right) {
|
|
33
37
|
return right + left;
|
|
34
38
|
}
|
|
35
39
|
};
|
|
@@ -50,26 +54,26 @@ class subtraction_facade<difference_type_, wide_size_type> {
|
|
|
50
54
|
using difference_type = difference_type_;
|
|
51
55
|
|
|
52
56
|
// Type -= difference_type
|
|
53
|
-
auto operator-=(this auto& self, difference_type offset) -> auto& { return self += -offset; }
|
|
57
|
+
constexpr auto operator-=(this auto& self, difference_type offset) -> auto& { return self += -offset; }
|
|
54
58
|
|
|
55
59
|
// --Type
|
|
56
|
-
auto operator--(this auto& self) -> auto& { return self -= 1; }
|
|
60
|
+
constexpr auto operator--(this auto& self) -> auto& { return self -= 1; }
|
|
57
61
|
|
|
58
62
|
// Type--
|
|
59
|
-
auto operator--(this auto& self, int) {
|
|
63
|
+
constexpr auto operator--(this auto& self, int) {
|
|
60
64
|
auto result = self;
|
|
61
65
|
--self;
|
|
62
66
|
return result;
|
|
63
67
|
}
|
|
64
68
|
|
|
65
69
|
// Type - difference_type
|
|
66
|
-
auto operator-(this const auto& self, difference_type offset) {
|
|
70
|
+
constexpr auto operator-(this const auto& self, difference_type offset) {
|
|
67
71
|
auto result = self;
|
|
68
72
|
return result -= offset;
|
|
69
73
|
}
|
|
70
74
|
|
|
71
75
|
// Type - Type
|
|
72
|
-
auto operator-(this const auto& self, decltype(self) right) -> difference_type {
|
|
76
|
+
constexpr auto operator-(this const auto& self, decltype(self) right) -> difference_type {
|
|
73
77
|
return static_cast<difference_type>(wide_size_type{+self} - wide_size_type{+right});
|
|
74
78
|
}
|
|
75
79
|
};
|
|
@@ -100,7 +104,7 @@ class arithmetic_facade
|
|
|
100
104
|
export template <class difference_type>
|
|
101
105
|
class array_facade {
|
|
102
106
|
public:
|
|
103
|
-
auto operator[](this auto&& self, difference_type offset) -> decltype(auto) {
|
|
107
|
+
constexpr auto operator[](this auto&& self, difference_type offset) -> decltype(auto) {
|
|
104
108
|
return *(std::forward<decltype(self)>(self) + offset);
|
|
105
109
|
}
|
|
106
110
|
};
|
package/utility/hash.cc
CHANGED
|
@@ -1,20 +1,15 @@
|
|
|
1
|
-
module;
|
|
2
|
-
#include <array>
|
|
3
|
-
#include <bit>
|
|
4
|
-
#include <cstdint>
|
|
5
|
-
#include <source_location>
|
|
6
|
-
#include <string_view>
|
|
7
1
|
export module util:utility.hash;
|
|
2
|
+
import std;
|
|
8
3
|
|
|
9
4
|
namespace util {
|
|
10
5
|
|
|
11
6
|
// `constexpr` hash for property lookup
|
|
12
7
|
export template <class Char>
|
|
13
|
-
constexpr auto fnv1a_hash(std::basic_string_view<Char> view) -> uint32_t {
|
|
14
|
-
constexpr uint32_t prime = 0x100'0193;
|
|
15
|
-
uint32_t hash = 0x811c'9dc5;
|
|
8
|
+
constexpr auto fnv1a_hash(std::basic_string_view<Char> view) -> std::uint32_t {
|
|
9
|
+
constexpr std::uint32_t prime = 0x100'0193;
|
|
10
|
+
std::uint32_t hash = 0x811c'9dc5;
|
|
16
11
|
for (auto character : view) {
|
|
17
|
-
auto bytes = std::bit_cast<std::array<uint8_t, sizeof(Char)>>(character);
|
|
12
|
+
auto bytes = std::bit_cast<std::array<std::uint8_t, sizeof(Char)>>(character);
|
|
18
13
|
for (auto byte : bytes) {
|
|
19
14
|
hash = hash ^ byte;
|
|
20
15
|
hash *= prime;
|
|
@@ -25,8 +20,8 @@ constexpr auto fnv1a_hash(std::basic_string_view<Char> view) -> uint32_t {
|
|
|
25
20
|
|
|
26
21
|
// constexpr `typeid(Type).hash_code()` replacement
|
|
27
22
|
template <class Type>
|
|
28
|
-
consteval auto make_type_hash() -> uint32_t {
|
|
29
|
-
// "uint32_t make_type_hash() [Type = int]"
|
|
23
|
+
consteval auto make_type_hash() -> std::uint32_t {
|
|
24
|
+
// "std::uint32_t make_type_hash() [Type = int]"
|
|
30
25
|
constexpr auto name = std::source_location::current().function_name();
|
|
31
26
|
return fnv1a_hash(std::string_view{name});
|
|
32
27
|
}
|
package/utility/ranges.cc
CHANGED
|
@@ -52,4 +52,15 @@ export constexpr auto into_range(meta_range auto&& range) {
|
|
|
52
52
|
return std::forward<decltype(range)>(range).into_range();
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
// Returns either a `std::tuple<size_type>` with the range's size, or `std::tuple<>` if it can't be
|
|
56
|
+
// determined in constant time.
|
|
57
|
+
export template <class Type>
|
|
58
|
+
constexpr auto maybe_range_size(const Type& range) {
|
|
59
|
+
if constexpr (std::ranges::sized_range<Type>) {
|
|
60
|
+
return std::tuple{std::ranges::size(range)};
|
|
61
|
+
} else {
|
|
62
|
+
return std::tuple{};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
55
66
|
} // namespace util
|
package/utility/string.cc
CHANGED
|
@@ -1,29 +1,20 @@
|
|
|
1
|
-
module;
|
|
2
|
-
#include <algorithm>
|
|
3
|
-
#include <array>
|
|
4
|
-
#include <bit>
|
|
5
|
-
#include <cstdint>
|
|
6
|
-
#include <limits>
|
|
7
|
-
#include <stdexcept>
|
|
8
|
-
#include <string>
|
|
9
|
-
#include <utility>
|
|
10
1
|
export module util:utility.string;
|
|
11
2
|
import :utility.constant_wrapper;
|
|
3
|
+
import std;
|
|
12
4
|
|
|
13
5
|
namespace util {
|
|
14
6
|
|
|
15
|
-
// Helper to make `std::string_view` from a constant_wrapper or string literal
|
|
16
7
|
export template <class Char, std::size_t Size>
|
|
17
|
-
struct consteval_string_view : public std::basic_string_view<Char> {
|
|
18
|
-
constexpr explicit consteval_string_view(const Char (&string)[ Size + 1 ]) noexcept : std::basic_string_view<Char>{string, Size} {}
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
template <class Char, std::size_t Size>
|
|
22
8
|
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
|
23
|
-
|
|
9
|
+
consteval auto make_consteval_string_view(const Char (&string)[ Size ]) -> std::basic_string_view<Char> {
|
|
10
|
+
return std::basic_string_view{string, Size - 1};
|
|
11
|
+
}
|
|
24
12
|
|
|
25
|
-
|
|
26
|
-
|
|
13
|
+
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
|
14
|
+
export template <class Char, std::size_t Size, fixed_value<Char[ Size ]> Value>
|
|
15
|
+
consteval auto make_consteval_string_view(constant_wrapper<Value> /*cw*/) -> std::basic_string_view<Char> {
|
|
16
|
+
return make_consteval_string_view(constant_wrapper<Value>::value);
|
|
17
|
+
}
|
|
27
18
|
|
|
28
19
|
// Helper for `codepoint_char_sequence` which stores an array of the most characters it will take to
|
|
29
20
|
// represent a codepoint in a given character type.
|
|
@@ -39,7 +30,7 @@ class codepoint_char_container {
|
|
|
39
30
|
|
|
40
31
|
[[nodiscard]] constexpr auto begin() const -> iterator { return chars_.begin(); }
|
|
41
32
|
[[nodiscard]] constexpr auto data() -> container_type& { return chars_; }
|
|
42
|
-
[[nodiscard]] constexpr auto end() const -> iterator { return std::
|
|
33
|
+
[[nodiscard]] constexpr auto end() const -> iterator { return std::find(std::next(chars_.begin()), chars_.end(), 0); }
|
|
43
34
|
[[nodiscard]] constexpr auto size() const -> std::size_t { return end() - begin(); }
|
|
44
35
|
|
|
45
36
|
private:
|
|
@@ -113,15 +104,8 @@ class codepoint_char_range<char16_t> : public codepoint_char_container<char16_t,
|
|
|
113
104
|
data()[ 1 ] = 0;
|
|
114
105
|
} else if (codepoint < 0x11'0000) {
|
|
115
106
|
auto twenty_bits = codepoint - 0x1'0000;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// | ^
|
|
119
|
-
// /usr/include/c++/v1/__type_traits/promote.h:38:1: note: previous definition is here
|
|
120
|
-
// 38 | using __promote_t _LIBCPP_NODEBUG =
|
|
121
|
-
// nb: `twenty_bits >> 10` == `twenty_bits / 0x400`
|
|
122
|
-
data()[ 0 ] = static_cast<char16_t>((twenty_bits >> 10) + 0xd800);
|
|
123
|
-
// nb: `twenty_bits & 0x3ff` == `twenty_bits % 0x400`
|
|
124
|
-
data()[ 1 ] = static_cast<char16_t>((twenty_bits & 0x3ff) + 0xdc00);
|
|
107
|
+
data()[ 0 ] = static_cast<char16_t>((twenty_bits / 0x400) + 0xd800);
|
|
108
|
+
data()[ 1 ] = static_cast<char16_t>((twenty_bits % 0x400) + 0xdc00);
|
|
125
109
|
} else {
|
|
126
110
|
std::unreachable();
|
|
127
111
|
}
|
|
@@ -188,7 +172,7 @@ class codepoint_utf8_forward_view {
|
|
|
188
172
|
constexpr auto read() -> char32_t {
|
|
189
173
|
// Check the expected length of the byte sequence from the leading byte's bit pattern
|
|
190
174
|
auto sequence_length = [ & ]() -> unsigned {
|
|
191
|
-
auto byte0 = std::bit_cast<uint8_t>(*pos_);
|
|
175
|
+
auto byte0 = std::bit_cast<std::uint8_t>(*pos_);
|
|
192
176
|
if (byte0 < 0x80) {
|
|
193
177
|
return 1;
|
|
194
178
|
} else if (byte0 < 0xe0) {
|
|
@@ -213,7 +197,7 @@ class codepoint_utf8_forward_view {
|
|
|
213
197
|
std::array<Char, 4> characters{};
|
|
214
198
|
std::ranges::copy_n(pos_, sequence_length, characters.begin());
|
|
215
199
|
pos_ += sequence_length;
|
|
216
|
-
auto [ byte0, byte1, byte2, byte3 ] = std::bit_cast<std::array<uint8_t, 4>>(characters);
|
|
200
|
+
auto [ byte0, byte1, byte2, byte3 ] = std::bit_cast<std::array<std::uint8_t, 4>>(characters);
|
|
217
201
|
|
|
218
202
|
// Convert byte sequence to codepoint
|
|
219
203
|
switch (sequence_length) {
|
|
@@ -249,14 +233,14 @@ class codepoint_forward_view<char16_t> {
|
|
|
249
233
|
|
|
250
234
|
constexpr auto read() -> char32_t {
|
|
251
235
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
252
|
-
auto char0 = *pos_
|
|
236
|
+
auto char0 = static_cast<char32_t>(*pos_++);
|
|
253
237
|
if (char0 >= 0xd800 && char0 < 0xdc00) {
|
|
254
238
|
if (eof()) {
|
|
255
239
|
// nb: Unpaired surrogate
|
|
256
240
|
return char0;
|
|
257
241
|
}
|
|
258
242
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
259
|
-
auto char1 = *pos_
|
|
243
|
+
auto char1 = static_cast<char32_t>(*pos_++);
|
|
260
244
|
if (char1 >= 0xdc00 && char1 < 0xe000) {
|
|
261
245
|
return ((char0 - 0xd800) * 0x400) + (char1 - 0xdc00) + 0x1'0000;
|
|
262
246
|
} else {
|
|
@@ -278,7 +262,7 @@ class codepoint_forward_view<char16_t> {
|
|
|
278
262
|
// Interpolate the given character range to a `std::basic_string<Char>`. If the requested character
|
|
279
263
|
// type is too small to represent a codepoint, a `std::range_error` is thrown.
|
|
280
264
|
export template <class To, class From>
|
|
281
|
-
constexpr auto
|
|
265
|
+
constexpr auto transcode_string(std::basic_string_view<From> from) -> std::basic_string<To> {
|
|
282
266
|
auto reader = codepoint_forward_view{from};
|
|
283
267
|
std::basic_string<To> result;
|
|
284
268
|
|
|
@@ -297,7 +281,7 @@ constexpr auto interpolate_string(std::basic_string_view<From> from) -> std::bas
|
|
|
297
281
|
}();
|
|
298
282
|
|
|
299
283
|
// Write string
|
|
300
|
-
result.resize_and_overwrite(size, [ & ](To* result, size_t /*length*/) -> size_t {
|
|
284
|
+
result.resize_and_overwrite(size, [ & ](To* result, std::size_t /*length*/) -> std::size_t {
|
|
301
285
|
auto first = result;
|
|
302
286
|
while (!reader.eof()) {
|
|
303
287
|
auto chunk = codepoint_char_range<To>{reader.read()};
|
|
@@ -311,14 +295,14 @@ constexpr auto interpolate_string(std::basic_string_view<From> from) -> std::bas
|
|
|
311
295
|
|
|
312
296
|
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
|
313
297
|
export template <class To, class From, std::size_t Extent, fixed_value<From[ Extent ]> Value>
|
|
314
|
-
constexpr auto
|
|
315
|
-
constexpr auto make = []() { return
|
|
298
|
+
constexpr auto transcode_string(util::constant_wrapper<Value> /*cw*/) {
|
|
299
|
+
constexpr auto make = []() { return transcode_string<To>(std::basic_string_view{Value.value, Extent - 1}); };
|
|
316
300
|
constexpr auto chars = [ = ]() {
|
|
317
301
|
std::array<To, make().size()> result{};
|
|
318
302
|
std::ranges::copy(make(), result.data());
|
|
319
303
|
return result;
|
|
320
304
|
}();
|
|
321
|
-
return [
|
|
305
|
+
return [ & ]<std::size_t... Indices>(std::index_sequence<Indices...>) {
|
|
322
306
|
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
|
323
307
|
constexpr To string[ chars.size() + 1 ] = {chars[ Indices ]..., 0};
|
|
324
308
|
return util::cw<string>;
|
package/utility/utility.cc
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
module;
|
|
2
|
-
#include <concepts>
|
|
3
|
-
#include <stdexcept>
|
|
4
|
-
#include <string_view>
|
|
5
|
-
#include <utility>
|
|
6
1
|
export module util:utility;
|
|
7
2
|
export import :utility.constant_wrapper;
|
|
8
3
|
export import :utility.covariant_value;
|
|
@@ -11,7 +6,7 @@ export import :utility.hash;
|
|
|
11
6
|
export import :utility.ranges;
|
|
12
7
|
export import :utility.string;
|
|
13
8
|
// export import :utility.variant;
|
|
14
|
-
import
|
|
9
|
+
import std;
|
|
15
10
|
|
|
16
11
|
namespace util {
|
|
17
12
|
|
|
@@ -40,11 +35,11 @@ export class non_moveable {
|
|
|
40
35
|
export template <std::size_t Size>
|
|
41
36
|
constexpr auto sequence = []() consteval -> auto {
|
|
42
37
|
// With C++26 P2686 we can do constexpr decomposition. So instead of the `tuple` of
|
|
43
|
-
// `integral_constants` it can be an array of `size_t`.
|
|
38
|
+
// `integral_constants` it can be an array of `std::size_t`.
|
|
44
39
|
// https://clang.llvm.org/cxx_status.html
|
|
45
40
|
|
|
46
41
|
// std::array<std::size_t, Size> result{};
|
|
47
|
-
// std::ranges::copy(std::ranges::
|
|
42
|
+
// std::ranges::copy(std::ranges::views::iota(std::size_t{0}, Size), result.begin());
|
|
48
43
|
// return result;
|
|
49
44
|
|
|
50
45
|
return []<std::size_t... Index>(std::index_sequence<Index...> /*sequence*/) consteval {
|
|
@@ -89,7 +84,7 @@ class just : public pointer_facade {
|
|
|
89
84
|
Type value_;
|
|
90
85
|
};
|
|
91
86
|
|
|
92
|
-
|
|
87
|
+
template <class Type>
|
|
93
88
|
class just<Type&> : public pointer_facade {
|
|
94
89
|
public:
|
|
95
90
|
explicit constexpr just(Type& value) : value_{&value} {}
|
|
@@ -143,8 +138,38 @@ struct slice_t<const Type> {
|
|
|
143
138
|
};
|
|
144
139
|
|
|
145
140
|
export template <class Type>
|
|
146
|
-
constexpr auto slice(Type& value) {
|
|
141
|
+
constexpr auto slice(const Type& value) {
|
|
147
142
|
return slice_t<const Type>{value};
|
|
148
143
|
}
|
|
149
144
|
|
|
145
|
+
// Implements construction of containers with variadic elements
|
|
146
|
+
template <class Type>
|
|
147
|
+
struct inplace_container_constructor {
|
|
148
|
+
constexpr auto operator()(auto&&... args) const -> Type {
|
|
149
|
+
return Type{std::in_place, std::forward<decltype(args)>(args)...};
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
template <class Type, std::size_t Size>
|
|
154
|
+
struct inplace_container_constructor<std::array<Type, Size>> {
|
|
155
|
+
constexpr auto operator()(auto&&... args) const -> std::array<Type, Size> {
|
|
156
|
+
return std::array<Type, Size>{std::forward<decltype(args)>(args)...};
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
template <class Type, class Alloc>
|
|
161
|
+
struct inplace_container_constructor<std::vector<Type, Alloc>> {
|
|
162
|
+
constexpr auto operator()(auto&&... args) const -> std::vector<Type, Alloc> {
|
|
163
|
+
auto container = std::vector<Type, Alloc>{};
|
|
164
|
+
container.reserve(sizeof...(args));
|
|
165
|
+
(..., container.emplace_back(std::forward<decltype(args)>(args)));
|
|
166
|
+
return container;
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
export template <class Type>
|
|
171
|
+
auto make_inplace_container(auto&&... args) -> Type {
|
|
172
|
+
return inplace_container_constructor<Type>{}(std::forward<decltype(args)>(args)...);
|
|
173
|
+
}
|
|
174
|
+
|
|
150
175
|
} // namespace util
|
package/utility/variant.cc
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
module;
|
|
2
|
-
#include <utility>
|
|
3
|
-
#include <variant>
|
|
4
1
|
export module util:utility.variant;
|
|
5
2
|
import :meta.algorithm;
|
|
6
|
-
import
|
|
3
|
+
import std;
|
|
7
4
|
|
|
8
5
|
namespace util {
|
|
9
6
|
|
|
10
7
|
// Apply a visitor to a variant and map its result to a new variant type. Repeated types are collapsed.
|
|
11
8
|
export auto map_variant(auto&& variant, auto visit) {
|
|
12
|
-
constexpr auto result_from = [](
|
|
13
|
-
return type<decltype(visit)>(type<util::apply_cvref_t<decltype(variant),
|
|
9
|
+
constexpr auto result_from = []<class Type>(std::type_identity<Type> /*alternative*/) {
|
|
10
|
+
return type<decltype(visit)>(type<util::apply_cvref_t<decltype(variant), Type>>);
|
|
14
11
|
};
|
|
15
12
|
const auto [... alternative_types ] = util::make_type_pack(util::remove_cvref(type<decltype(variant)>));
|
|
16
13
|
const auto [... result_types ] = util::pack_unique(result_from(alternative_types)...);
|