header_utils
Loading...
Searching...
No Matches
functional.h
1
4
5#pragma once
6
7#include "min-cpp-version/cpp17.h"
8#include <functional>
9#include <optional>
10#include <type_traits>
11#include <variant>
12#if defined(__cpp_lib_bit_cast)
13#include <bit>
14#endif
15
16namespace ghassanpl
17{
21
23 template <typename... ARGS>
24 [[nodiscard]] constexpr auto make_single_time_function(std::function<void(ARGS...)> func)
25 {
26 return[func = std::move(func)](auto&&... args) mutable {
27 if (func) std::exchange(func, {})(std::forward<decltype(args)>(args)...);
28 };
29 }
30
32 template <typename FUNC>
33 [[nodiscard]] constexpr auto make_single_time_function(FUNC&& func)
34 {
35 return make_single_time_function(std::function{ std::forward<FUNC>(func) });
36 }
37
39 template <typename T, typename FUNC>
40 [[nodiscard]] constexpr auto transformed(std::optional<T> const& value, FUNC&& func) -> decltype(std::optional{ func(value.value()) })
41 {
42 return value ? std::optional{ func(value.value()) } : std::nullopt;
43 }
44
46 template <typename T, typename FUNC>
47 [[nodiscard]] constexpr auto transformed(std::optional<T>&& value, FUNC&& func) -> decltype(std::optional{ func(value.value()) })
48 {
49 return value ? std::optional{ func(std::move(value).value()) } : std::nullopt;
50 }
51
52 template <typename T>
53 std::optional<T> to_optional(T* value) noexcept { return value ? *value : std::nullopt; }
54
55 template <typename T>
56 std::optional<T> move_to_optional(T* value) noexcept { return value ? std::move(*value) : std::nullopt; }
57
59 template <typename T> [[nodiscard]] constexpr auto flattened(std::optional<std::optional<T>>&& value) { return value ? flatten(std::move(value).value()) : std::nullopt; }
60 template <typename T> [[nodiscard]] constexpr auto flattened(std::optional<T>&& value) { return value; }
61 template <typename T> [[nodiscard]] constexpr auto flattened(std::optional<std::optional<T>> const& value) { return value ? flatten(value.value()) : std::nullopt; }
62 template <typename T> [[nodiscard]] constexpr auto flattened(std::optional<T> const& value) { return value; }
63
73 template <class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
74
76 #define GHPL_OVERLOAD(...) [&](auto &&... args) -> decltype(auto) { \
77 return __VA_ARGS__(std::forward<decltype(args)>(args)...); \
78 }
79
81 namespace pred
82 {
83 // TODO: Boost::phoenix::arg_names is a better version of this
84
85 [[nodiscard]] constexpr auto always_true() { return [](auto&& other) { return true; }; }
86
87 template <typename T> [[nodiscard]] constexpr auto equal_to(T&& val) { return [val = std::forward<T>(val)](auto&& other) { return other == val; }; }
88 template <typename T> [[nodiscard]] constexpr auto not_equal_to(T&& val) { return [val = std::forward<T>(val)](auto&& other) { return other != val; }; }
89 template <typename T> [[nodiscard]] constexpr auto less_than(T&& val) { return [val = std::forward<T>(val)](auto&& other) { return other < val; }; }
90 template <typename T> [[nodiscard]] constexpr auto less_than_or_equal_to(T&& val) { return [val = std::forward<T>(val)](auto&& other) { return other <= val; }; }
91 template <typename T> [[nodiscard]] constexpr auto greater_than(T&& val) { return [val = std::forward<T>(val)](auto&& other) { return other > val; }; }
92 template <typename T> [[nodiscard]] constexpr auto greater_than_or_equal_to(T&& val) { return [val = std::forward<T>(val)](auto&& other) { return other >= val; }; }
93
94 template <typename T> [[nodiscard]] constexpr auto eq(T&& val) { return [val = std::forward<T>(val)](auto&& other) { return other == val; }; }
95 template <typename T> [[nodiscard]] constexpr auto ne(T&& val) { return [val = std::forward<T>(val)](auto&& other) { return other != val; }; }
96 template <typename T> [[nodiscard]] constexpr auto lt(T&& val) { return [val = std::forward<T>(val)](auto&& other) { return other < val; }; }
97 template <typename T> [[nodiscard]] constexpr auto le(T&& val) { return [val = std::forward<T>(val)](auto&& other) { return other <= val; }; }
98 template <typename T> [[nodiscard]] constexpr auto gt(T&& val) { return [val = std::forward<T>(val)](auto&& other) { return other > val; }; }
99 template <typename T> [[nodiscard]] constexpr auto ge(T&& val) { return [val = std::forward<T>(val)](auto&& other) { return other >= val; }; }
100
101 [[nodiscard]] constexpr auto is_null() noexcept { return [](auto&& other) { return other == nullptr; }; }
102 [[nodiscard]] constexpr auto is_not_null() noexcept { return [](auto&& other) { return other != nullptr; }; }
103 [[nodiscard]] constexpr auto is_empty() noexcept { return [](auto&& other) { return std::empty(other); }; }
104 [[nodiscard]] constexpr auto is_not_empty() noexcept { return [](auto&& other) { return !std::empty(other); }; }
105 [[nodiscard]] constexpr auto is_true() noexcept { return [](auto&& other) { return !!other; }; }
106 [[nodiscard]] constexpr auto is_false() noexcept { return [](auto&& other) { return !other; }; }
107 template <typename T> [[nodiscard]] constexpr auto is_in(T&& val) { return [val = std::forward<T>(val)](auto&& other) { return std::find(std::begin(val), std::end(val), other) != std::end(val); }; }
108
109 template <typename... FUNCS>
110 [[nodiscard]] constexpr auto when_any(FUNCS&&... funcs) {
111 return [funcs = std::make_tuple(std::forward<FUNCS>(funcs)...)](auto&&... args) {
112 return std::apply([&](auto&&... funcs) {
113 return (funcs(args...) || ...);
114 }, funcs);
115 };
116 }
117
118 template <typename... FUNCS>
119 [[nodiscard]] constexpr auto when_all(FUNCS&&... funcs) {
120 return [funcs = std::make_tuple(std::forward<FUNCS>(funcs)...)](auto&&... args) {
121 return std::apply([&](auto&&... funcs) {
122 return (funcs(args...) && ...);
123 }, funcs);
124 };
125 }
126
127 template <typename... FUNCS>
128 [[nodiscard]] constexpr auto when_none(FUNCS&&... funcs) {
129 return [funcs = std::make_tuple(std::forward<FUNCS>(funcs)...)](auto&&... args) {
130 return std::apply([&](auto&&... funcs) {
131 return !(funcs(args...) || ...);
132 }, funcs);
133 };
134 }
135
136
138 /*
139 template <typename FUNC>
140 [[nodiscard]] constexpr auto negated(FUNC&& func)
141 {
142 return [func = std::forward<FUNC>(func)](auto&&... args) { return !func(std::forward<decltype(args)>(args)...); };
143 }
144 */
145 }
146
148 namespace op
149 {
150 template <typename T> [[nodiscard]] constexpr auto push_back_to(T& to) noexcept { return [&to](auto&& val) { to.push_back(std::forward<decltype(val)>(val)); }; }
151 template <typename T> [[nodiscard]] constexpr auto emplace_back_to(T& to) noexcept { return [&to](auto&& val) { to.emplace_back(std::forward<decltype(val)>(val)); }; }
152 template <typename T> [[nodiscard]] constexpr auto push_front_to(T& to) noexcept { return [&to](auto&& val) { to.push_front(std::forward<decltype(val)>(val)); }; }
153 template <typename T> [[nodiscard]] constexpr auto emplace_front_to(T& to) noexcept { return [&to](auto&& val) { to.emplace_front(std::forward<decltype(val)>(val)); }; }
154 template <typename T> [[nodiscard]] constexpr auto append_to(T& to) noexcept { return [&to](auto&& val) { to.append(std::forward<decltype(val)>(val)); }; }
155 template <typename T> [[nodiscard]] constexpr auto insert_to(T& to) noexcept { return [&to](auto&& val) { to.insert(std::forward<decltype(val)>(val)); }; }
156
157 template <typename T, GHPL_TYPENAME(std::output_iterator<T>) IT>
158 [[nodiscard]] constexpr auto output_to(IT&& to) { return [to = std::forward<IT>(to)](auto&& val) { *to++ = std::forward<decltype(val)>(val); }; }
159
160 template <typename T> [[nodiscard]] constexpr auto assign_to(T& to) noexcept { return [&to](auto&& val) { to = std::forward<decltype(val)>(val); }; }
161 template <typename T> [[nodiscard]] constexpr auto add_to(T& to) noexcept { return [&to](auto&& val) { to += std::forward<decltype(val)>(val); }; }
162 template <typename T> [[nodiscard]] constexpr auto stream_to(T& to) noexcept { return [&to](auto&& val) { to << std::forward<decltype(val)>(val); }; }
163 template <typename T> [[nodiscard]] constexpr auto stream_from(T& from) noexcept { return [&from](auto&& val) { from >> std::forward<decltype(val)>(val); }; }
164
167 template <typename... FUNCS>
168 [[nodiscard]] constexpr auto call_all(FUNCS&&... funcs)
169 {
170 return [funcs = std::make_tuple(std::forward<FUNCS>(funcs)...)](auto&&... args) {
171 return std::apply([&](auto&&... funcs) {
172 return (funcs(args...), ...);
173 }, funcs);
174 };
175 }
176
177 template <typename F>
178 [[nodiscard]] constexpr auto call_composed(F&& f)
179 {
180 return std::forward<F>(f);
181 }
182
184 template <typename F, typename ... Fs>
185 [[nodiscard]] constexpr auto call_composed(F&& f, Fs&&... fs)
186 {
187 return [first = std::forward<F>(f), rest = call_composed(std::forward<Fs>(fs)...)](auto&&... args) {
188 return first(rest(std::forward<decltype(args)>(args)...));
189 };
190 }
191
192 template <typename F>
193 [[nodiscard]] constexpr auto call_piped(F&& f)
194 {
195 return std::forward<F>(f);
196 }
197
199 template <typename F, typename ... Fs>
200 [[nodiscard]] constexpr auto call_piped(F&& f, Fs&&... fs)
201 {
202 return [first = std::forward<F>(f), rest = call_composed(std::forward<Fs>(fs)...)](auto&&... args) {
203 return rest(first(std::forward<decltype(args)>(args)...));
204 };
205 }
206
208 template <typename THEN, typename IF>
209 [[nodiscard]] constexpr auto call_when(THEN&& op, IF&& predicate)
210 {
211 return [predicate = std::forward<IF>(predicate), op = std::forward<THEN>(op)](auto&&... args) {
212 if (predicate(args...))
213 op(std::forward<decltype(args)>(args)...);
214 };
215 }
216
218 template <typename THEN, typename IF, typename ELSE_VAL>
219 [[nodiscard]] constexpr auto call_when(THEN&& op, IF&& predicate, ELSE_VAL&& elseval)
220 {
221 return [predicate = std::forward<IF>(predicate), op = std::forward<THEN>(op), elseval = std::forward<ELSE_VAL>(elseval)](auto&&... args)
222 -> std::common_type_t<
223 decltype(op(std::forward<decltype(args)>(args)...)),
224 decltype(std::forward<ELSE_VAL>(elseval))
225 >
226 {
227 if (predicate(args...))
228 return op(std::forward<decltype(args)>(args)...);
229 return std::forward<ELSE_VAL>(elseval);
230 };
231 }
232
234 template <typename THEN, typename IF, typename ELSE>
235 [[nodiscard]] constexpr auto call_when_else(THEN&& op, IF&& predicate, ELSE&& elseop)
236 {
237 return [predicate = std::forward<IF>(predicate), op = std::forward<THEN>(op), elseop = std::forward<ELSE>(elseop)](auto&&... args)
238 -> std::common_type_t<
239 decltype(op(std::forward<decltype(args)>(args)...)),
240 decltype(elseop(std::forward<decltype(args)>(args)...))
241 >
242 {
243 if (predicate(args...))
244 return op(std::forward<decltype(args)>(args)...);
245 else
246 return elseop(std::forward<decltype(args)>(args)...);
247 };
248 }
249
250 }
251
253 namespace xf
254 {
255 [[nodiscard]] constexpr auto identity() noexcept { return [](auto&& val) { return std::forward<decltype(val)>(val); }; }
256 constexpr auto identity_l = [] (auto&& val) noexcept { return std::forward<decltype(val)>(val); };
257
258 template <typename T> [[nodiscard]] constexpr auto cast_to() noexcept { return [](auto&& val) { return (T)std::forward<decltype(val)>(val); }; }
259 template <typename T> [[nodiscard]] constexpr auto dynamic_cast_to() noexcept { return [](auto&& val) { return dynamic_cast<T>(std::forward<decltype(val)>(val)); }; }
260#if defined(__cpp_lib_bit_cast)
261 template <typename T> [[nodiscard]] constexpr auto bit_cast_to() noexcept { return [](auto&& val) { return std::bit_cast<T>(std::forward<decltype(val)>(val)); }; }
262#endif
263 template <typename T> [[nodiscard]] constexpr auto constructed_as() noexcept { return [](auto&& val) { return T{ std::forward<decltype(val)>(val) }; }; }
264 [[nodiscard]] constexpr auto called() noexcept { return [](auto&& val) { return std::forward<decltype(val)>(val)(); }; }
265
266 template <typename T> [[nodiscard]] constexpr auto added_to(T&& other) noexcept { return [other = std::forward<T>(other)](auto&& val) { return std::forward<decltype(val)>(val) + other; }; }
267 template <typename T> [[nodiscard]] constexpr auto subtracted_from(T&& other) noexcept { return [other = std::forward<T>(other)](auto&& val) { return other - std::forward<decltype(val)>(val); }; }
268 template <typename T> [[nodiscard]] constexpr auto decremented_by(T&& other) noexcept { return [other = std::forward<T>(other)](auto&& val) { return std::forward<decltype(val)>(val) - other; }; }
269 template <typename T> [[nodiscard]] constexpr auto divided_by(T&& other) noexcept { return [other = std::forward<T>(other)](auto&& val) { return std::forward<decltype(val)>(val) / other; }; }
270 template <typename T> [[nodiscard]] constexpr auto overed_by(T&& other) noexcept { return [other = std::forward<T>(other)](auto&& val) { return other / std::forward<decltype(val)>(val); }; }
271 template <typename T> [[nodiscard]] constexpr auto modulo_by(T&& other) noexcept { return [other = std::forward<T>(other)](auto&& val) { return std::forward<decltype(val)>(val) % other; }; }
272 template <typename T> [[nodiscard]] constexpr auto multiplied_by(T&& other) noexcept { return [other = std::forward<T>(other)](auto&& val) { return std::forward<decltype(val)>(val) * other; }; }
273 [[nodiscard]] constexpr auto complemented() noexcept { return [](auto&& val) { return -std::forward<decltype(val)>(val); }; }
274
275 [[nodiscard]] constexpr auto negated() noexcept { return [](auto&& val) { return !std::forward<decltype(val)>(val); }; }
276
277 [[nodiscard]] constexpr auto bit_inverted() noexcept { return [](auto&& val) { return ~std::forward<decltype(val)>(val); }; }
278 template <typename T> [[nodiscard]] constexpr auto bit_anded_with(T&& other) noexcept { return [other = std::forward<T>(other)](auto&& val) { return std::forward<decltype(val)>(val) & other; }; }
279 template <typename T> [[nodiscard]] constexpr auto bit_ored_with(T&& other) noexcept { return [other = std::forward<T>(other)](auto&& val) { return std::forward<decltype(val)>(val) | other; }; }
280 template <typename T> [[nodiscard]] constexpr auto bit_xored_with(T&& other) noexcept { return [other = std::forward<T>(other)](auto&& val) { return std::forward<decltype(val)>(val) ^ other; }; }
281 template <typename T> [[nodiscard]] constexpr auto shifted_left_by(T&& other) noexcept { return [other = std::forward<T>(other)](auto&& val) { return std::forward<decltype(val)>(val) << other; }; }
282 template <typename T> [[nodiscard]] constexpr auto shifted_right_by(T&& other) noexcept { return [other = std::forward<T>(other)](auto&& val) { return std::forward<decltype(val)>(val) >> other; }; }
283
284 template <typename T> [[nodiscard]] constexpr auto field(T&& field_ptr) noexcept {
285 return [field_ptr = std::forward<T>(field_ptr)](auto&& val) {
286 using arg_type = remove_cvref_t<decltype(val)>;
287 if constexpr (std::is_pointer_v<arg_type>)
288 return (std::forward<decltype(val)>(val)->*field_ptr);
289 else
290 return (std::forward<decltype(val)>(val).*field_ptr);
291 };
292 }
293
294#ifdef __cpp_impl_three_way_comparison
295 template <typename T> [[nodiscard]] constexpr auto compared_with(T&& other) noexcept { return [other = std::forward<T>(other)](auto&& val) { return std::forward<decltype(val)>(val) <=> other; }; }
296#endif
297
298 }
299
302#define std_call(func) ([](auto&&... vals) { return std::func(std::forward<decltype(vals)>(vals)...); })
303
305 template <typename T, typename FUNC>
306 constexpr T resulting(FUNC&& func)
307 {
308 T result{};
309 func(result);
310 return result;
311 }
312
313 namespace detail
314 {
315 template <typename Ret, typename Arg, typename = std::enable_if_t<
316 std::is_lvalue_reference_v<Arg> &&
317 !std::is_const_v<std::remove_reference_t<Arg>>&&
318 std::is_default_constructible_v<std::remove_reference_t<Arg>>>
319 >
320 constexpr auto detect_first_arg(std::function<Ret(Arg)>) {
321 return type_identity<Arg>{};
322 }
323 constexpr auto detect_first_arg(...) {
324 return type_identity<void>{};
325 }
326 }
327
329 template <typename FUNC>
330 GHPL_REQUIRES((!std::is_void_v<typename decltype(detail::detect_first_arg(std::function{ std::declval<FUNC>() }))::type>&& requires { std::function{ std::declval<FUNC>() }; }))
331 constexpr auto resulting(FUNC&& func)
332 {
335 using arg_type = typename decltype(detail::detect_first_arg(std::function{ std::declval<FUNC>() }))::type;
336 static_assert(!std::is_void_v<arg_type>, "function must take a single l-value reference argument");
337 std::remove_reference_t<arg_type> result{};
338 func(result);
339 return result;
340 }
341
343
345 template <typename T, typename... ARGS>
346 [[nodiscard]] constexpr std::optional<T> optional_get(std::variant<ARGS...> const& var) noexcept
347 {
348 if (std::holds_alternative<T>(var))
349 return std::get<T>(var);
350 return std::nullopt;
351 }
352
353 /*
354 template <typename T, typename E, typename... ARGS>
355 [[nodiscard]] constexpr std::expected<T, E> get_or(std::variant<ARGS...> const& var, E&& error) noexcept
356 {
357 if (std::holds_alternative<T>(var))
358 return std::get<T>(var);
359 return std::unexpected(std::forward<E>(error));
360 }
361 */
362
363
364 namespace detail
365 {
366 template<class... T> struct mp_list {};
367
368 template <typename T, typename... TT>
369 constexpr bool mp_set_contains() { return (std::is_same_v<TT, T> || ...); }
370 template <typename T, typename... TT>
371 constexpr bool mp_set_contains(mp_list<TT...>) { return (std::is_same_v<TT, T> || ...); }
372
373 template <typename...TT, typename T>
374 constexpr auto operator&(mp_list<TT...>, mp_list<T>) ->
375 std::conditional_t<(std::is_same_v<TT, T> || ...),
376 mp_list<TT...>,
377 mp_list<TT..., T>
378 >;
379 template <typename...TT, typename T>
380 constexpr auto operator+(mp_list<TT...>, mp_list<T>) -> mp_list<TT..., T>;
381
382 template <template <typename...> typename TMPL, typename... Ts>
383 constexpr auto mp_apply(mp_list<Ts...>) -> TMPL<Ts...>;
384
385 /*
386 template<class L> struct mp_make_unique_impl;
387 template<template<class...> class L, class... T>
388 struct mp_make_unique_impl<L<T...>> {
389 using type = decltype(mp_apply<L>((mp_list<>{} & ... & mp_list<T>{})));
390 };
391 template<class L> using mp_make_unique = typename mp_make_unique_impl<L>::type;
392 */
393 template<template<class...> class L, class... T>
394 constexpr auto mp_make_unique(L<T...>) -> decltype(mp_apply<L>((mp_list<>{} & ... & mp_list<T>{})));
395 }
396
398 template <typename FUNC, typename... Ts>
399 constexpr auto transformed(std::variant<Ts...> const& var, FUNC&& func)
400 {
401 using result_type = decltype(detail::mp_make_unique(std::variant<
402 decltype(func(std::declval<Ts>()))...
403 >{}));
404 return std::visit([&func](auto&& val) -> result_type { return result_type(func(std::forward<decltype(val)>(val))); }, var);
405 }
406
407
408 namespace detail
409 {
410
411 template <typename... Ts1, typename... Ts2>
412 constexpr auto cat_lists(mp_list<Ts1...>, mp_list<Ts2...>) -> mp_list<Ts1..., Ts2...>;
413
414 template <typename... Ts>
415 constexpr auto flatten(mp_list<std::variant<Ts...>>) -> decltype(flatten(mp_list<Ts...>{}));
416
417 template <typename T>
418 constexpr auto flatten(mp_list<T>) -> mp_list<T>;
419
420 template <typename T, typename T2, typename... Ts>
421 constexpr auto flatten(mp_list<T, T2, Ts...>)
422 -> decltype(cat_lists(cat_lists(flatten(mp_list<T>{}), flatten(mp_list<T2>{})), mp_list<Ts... >{}));
423
424 template <typename... Ts>
425 using flattened = decltype(flatten(mp_list<Ts...>{}));
426
427 template <template <typename...> typename TMPL, typename T1, typename T2, typename... Ts>
428 constexpr auto mp_apply_or_single(mp_list<T1, T2, Ts...>) -> TMPL<T1, T2, Ts...>;
429 template <template <typename...> typename TMPL, typename T>
430 constexpr auto mp_apply_or_single(mp_list<T>) -> T;
431
432 //template <typename T, typename Ts...> using first_only = T;
433 template <typename T, typename... Ts>
434 using variant_flat_t = decltype(mp_apply_or_single<std::variant>(detail::mp_make_unique(flattened<T, Ts...>{})));
435 }
436
437 template <typename... TYPES>
438 struct convertible_to_variant
439 {
440 std::variant<TYPES...> value;
441
442 convertible_to_variant() noexcept = delete;
443 convertible_to_variant(convertible_to_variant&&) noexcept = default;
444 convertible_to_variant& operator=(convertible_to_variant&&) noexcept = default;
445
446 convertible_to_variant(std::variant<TYPES...> val) noexcept : value(std::move(val)) {}
447 convertible_to_variant& operator=(std::variant<TYPES...> val) noexcept { std::swap(value, val); return *this; }
448
449 template <typename... OTHER_TYPES,
450 typename = std::enable_if_t<!std::is_same_v<decltype(value), std::variant<OTHER_TYPES...>>>,
451 typename = std::enable_if_t<(detail::mp_set_contains<TYPES, OTHER_TYPES...>() && ...)>
452 >
453 operator std::variant<OTHER_TYPES...>() && noexcept
454 {
455 static_assert((detail::mp_set_contains<TYPES, OTHER_TYPES...>() && ...), "not every type in source variant is present in destination variant");
456
457 return std::visit(overloaded{
458 [](TYPES&& val) -> std::variant<OTHER_TYPES...> {
459 return std::variant<OTHER_TYPES...>(std::move(val));
460 }...
461 }, std::move(value));
462 }
463
464 operator std::variant<TYPES...>() && noexcept {
465 return std::move(value);
466 }
467 };
468
469 template <typename... TYPES>
470 convertible_to_variant(std::variant<TYPES...>) -> convertible_to_variant<TYPES...>;
471 template <typename T>
472 convertible_to_variant(T) -> convertible_to_variant<remove_cvref_t<T>>;
473
474#ifndef __clang__
476 template <typename FUNC, typename... Ts>
477 constexpr auto transformed_flattened(std::variant<Ts...> const& var, FUNC&& func)
478 {
479 using result_type = decltype(detail::mp_make_unique(
480 detail::variant_flat_t<decltype(func(std::declval<Ts>()))...>{}
481 ));
482 return std::visit([&func](auto&& val) -> result_type { return convertible_to_variant(func(std::forward<decltype(val)>(val))); }, var);
483 }
484#endif
485
487}
constexpr auto transformed_flattened(std::variant< Ts... > const &var, FUNC &&func)
Returns a new variant transformed by func, flattened.
Definition functional.h:477
constexpr auto make_single_time_function(std::function< void(ARGS...)> func)
Returns a function that calls func when invoked, but only the first time.
Definition functional.h:24
constexpr T resulting(FUNC &&func)
Returns a new T transformed by func.
Definition functional.h:306
constexpr auto transformed(std::optional< T > const &value, FUNC &&func) -> decltype(std::optional{ func(value.value()) })
Pre C++23 transform/fmap.
Definition functional.h:40
constexpr std::optional< T > optional_get(std::variant< ARGS... > const &var) noexcept
Variant operations.
Definition functional.h:346
constexpr CONTAINER to(RANGE &&range, TYPES &&... args)
to<container>();
Definition ranges.h:386
The below code is based on Sun's libm library code, which is licensed under the following license:
Contains functions that return functors that perform an operation without output; appropriate for fun...
Definition functional.h:149
constexpr auto call_when(THEN &&op, IF &&predicate)
Acts as if (predicate(args...)) op(args...);.
Definition functional.h:209
constexpr auto call_piped(F &&f)
forwarding F can throw
Definition functional.h:193
constexpr auto call_composed(F &&f)
forwarding F can throw
Definition functional.h:178
constexpr auto call_when_else(THEN &&op, IF &&predicate, ELSE &&elseop)
Acts as if (predicate(args...)) return op(args...); else return elseop(args...);.
Definition functional.h:235
constexpr auto call_all(FUNCS &&... funcs)
For funcs a, b, c, calls them as return (a(args...), b(args...), c(args...)).
Definition functional.h:168
Contains functions that return predicates; appropriate for functions like std::all_of.
Definition functional.h:82
Contains functions that return functors which transform and return their inputs somehow; appropriate ...
Definition functional.h:254
Primary namespace for everything in this library.
Definition align+rec2.h:10
GHPL_REQUIRES(std::is_enum_v< ENUM_TYPE >) struct circular_enum
TODO: Finish this.
Definition enums.h:23
Can be used to create an object with an overload set of operator() if constructed from multiple lambd...
Definition functional.h:73