halcheck 1.0
Loading...
Searching...
No Matches
utility.hpp
1#ifndef HALCHECK_LIB_UTILITY_HPP
2#define HALCHECK_LIB_UTILITY_HPP
3
11#include <halcheck/lib/functional.hpp>
12#include <halcheck/lib/type_traits.hpp>
13#include <halcheck/lib/variant.hpp>
14
15#include <cstddef>
16#include <exception>
17#include <utility> // IWYU pragma: export
18
19namespace halcheck { namespace lib {
20
26struct in_place_t {};
27
33static constexpr in_place_t in_place;
34
40template<typename T, typename U = T>
41T exchange(T &value, U &&next) {
42 T prev = std::move(value);
43 value = std::forward<U>(next);
44 return prev;
45}
46
52template<typename T, T... Ints>
54
60template<std::size_t... Ints>
62
63namespace detail {
64template<typename, typename T, T N, T... Ints>
66
67template<typename T, T N, T... Ints>
68struct make_integer_sequence<lib::enable_if_t<N == 0>, T, N, Ints...> : integer_sequence<T, Ints...> {};
69
70template<typename T, T N, T... Ints>
71struct make_integer_sequence<lib::enable_if_t<N != 0>, T, N, Ints...>
72 : make_integer_sequence<void, T, N - 1, N - 1, Ints...> {};
73
74} // namespace detail
75
81template<typename T, T N>
82struct make_integer_sequence : detail::make_integer_sequence<void, T, N> {};
83
89template<std::size_t N>
91
92template<typename T>
93class result_holder {
94public:
95 explicit result_holder(T value) : _value(std::move(value)) {}
96 explicit result_holder(std::exception_ptr value) : _value(std::move(value)) {}
97
98 T &get() & {
99 return lib::visit(
101 [](T &value) -> T & { return value; },
102 [](std::exception_ptr e) -> T & { std::rethrow_exception(std::move(e)); }),
103 _value);
104 }
105
106 const T &get() const & { return const_cast<result_holder *>(this)->get(); }
107
108 explicit operator bool() const { return lib::holds_alternative<std::exception_ptr>(_value); }
109
110private:
111 lib::variant<T, std::exception_ptr> _value;
112};
113
114template<typename T>
115class result_holder<T &> {
116public:
117 explicit result_holder(T &value) : _value(&value) {}
118 explicit result_holder(std::exception_ptr value) : _value(std::move(value)) {}
119
120 T &get() & {
121 return lib::visit(
123 [](T *value) -> T & { return *value; },
124 [](std::exception_ptr e) -> T & { std::rethrow_exception(std::move(e)); }),
125 _value);
126 }
127
128 const T &get() const & { return const_cast<result_holder *>(this)->get(); }
129
130 explicit operator bool() const { return lib::holds_alternative<std::exception_ptr>(_value); }
131
132private:
133 lib::variant<T *, std::exception_ptr> _value;
134};
135
136template<>
137class result_holder<void> {
138public:
139 explicit result_holder(std::exception_ptr value = nullptr) : _value(std::move(value)) {}
140
141 void get() const {
142 if (_value)
144 }
145
146private:
147 std::exception_ptr _value;
148};
149
150template<typename F, typename... Args, HALCHECK_REQUIRE(!std::is_void<lib::invoke_result_t<F, Args...>>())>
151lib::result_holder<lib::invoke_result_t<F, Args...>> make_result_holder(F func, Args &&...args) {
152 try {
153 return lib::result_holder<lib::invoke_result_t<F, Args...>>(lib::invoke(func, std::forward<Args>(args)...));
154 } catch (...) {
155 return lib::result_holder<lib::invoke_result_t<F, Args...>>(std::current_exception());
156 }
157}
158
159template<typename F, typename... Args, HALCHECK_REQUIRE(std::is_void<lib::invoke_result_t<F, Args...>>())>
160lib::result_holder<void> make_result_holder(F func, Args &&...args) {
161 try {
162 lib::invoke(func, std::forward<Args>(args)...);
163 return lib::result_holder<void>();
164 } catch (...) {
165 return lib::result_holder<void>(std::current_exception());
166 }
167}
168
169}} // namespace halcheck::lib
170
171#endif
T current_exception(T... args)
T forward(T... args)
HALCHECK_INLINE_CONSTEXPR struct halcheck::lib::@20 invoke
An implementation of std::invoke.
lib::overload< Args... > make_overload(Args... args)
Constructs an overloaded functor from a set of pre-existing functors.
Definition overload.hpp:48
decltype(lib::invoke(std::declval< F >(), std::declval< Args >()...)) invoke_result_t
An implementation of std::invoke_result_t.
Definition invoke.hpp:42
typename std::enable_if< Cond, T >::type enable_if_t
An implementation of std::enable_if_t.
Definition type_traits.hpp:93
#define HALCHECK_REQUIRE(...)
Expands to a template argument that is only valid if the given argument evaluates to true.
Definition type_traits.hpp:24
T exchange(T &value, U &&next)
An implementation of std::exchange.
Definition utility.hpp:41
static constexpr in_place_t in_place
An implementation of std::in_place.
Definition utility.hpp:33
STL namespace.
T rethrow_exception(T... args)
An implementation of std::in_place_t.
Definition utility.hpp:26
An implementation of std::integer_sequence.
Definition utility.hpp:53
An implementation of std::make_integer_sequence.
Definition utility.hpp:82