Krita Source Code Documentation
Loading...
Searching...
No Matches
KisMpl.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2021 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#ifndef KISMPL_H
8#define KISMPL_H
9
10#include <tuple>
11#include <utility>
12#include <optional>
13#include <functional>
14
18namespace kismpl {
19
20namespace detail {
21
22template<std::size_t ...Idx>
24
25template<std::size_t num, std::size_t ...Idx>
27 using type = typename make_index_sequence_from_1_impl<num - 1, num, Idx...>::type;
28};
29
30template<std::size_t ...Idx>
32 using type = std::index_sequence<Idx...>;
33};
34
35} // namespace detail
36
43template<std::size_t Num>
46
47namespace detail {
48
49template <typename F, typename Tuple, std::size_t... I>
50auto apply_to_tuple_impl(F f, Tuple &&t, std::index_sequence<I...>) {
51 return std::make_tuple(f(std::get<I>(std::forward<Tuple>(t)))...);
52}
53}
54
59template <typename F, typename Tuple>
60auto apply_to_tuple(F f, Tuple &&t) {
61 return detail::apply_to_tuple_impl(std::forward<F>(f), std::forward<Tuple>(t),
62 std::make_index_sequence<std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
63}
64
70constexpr auto unzip_wrapper = [] (auto f) {
71 return
72 [=] (auto &&x) {
73 return std::apply(f, std::forward<decltype(x)>(x));
74 };
75};
76
77namespace detail {
78
79template <typename First, typename... Rest>
81{
82 using type = First;
83};
84
85}
86
90template <typename... T>
92{
93 using type = typename detail::first_type_impl<T...>::type;
94};
95
100template <typename... T>
101using first_type_t = typename first_type<T...>::type;
102
103namespace detail {
104template <typename Fun, typename T>
106 std::optional<T> fold(const std::optional<T> &first) {
107 return first;
108 }
109
110 std::optional<T> fold(const std::optional<T> &first, const std::optional<T> &second) {
111 if (first && second) {
112 return m_fun(*first, *second);
113 } else if (first) {
114 return first;
115 } else {
116 return second;
117 }
118 }
119
120 template <typename... Rest>
121 std::optional<T> fold(const std::optional<T> &first, std::optional<T> const &second, const std::optional<Rest> &...rest) {
122 return fold(fold(first, second), rest...);
123 }
124
125 const Fun m_fun;
126};
127
128} // namespace detail
129
135template <typename Fun, typename... Args,
136 typename T = typename first_type_t<std::remove_reference_t<Args>...>::value_type>
137std::optional<T> fold_optional(Fun &&fun, Args &&...args) {
138 return detail::fold_optional_impl<Fun, T>{std::forward<Fun>(fun)}.fold(args...);
139}
140
144template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
145template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
146
147namespace detail {
148
149template<typename Op, typename Class, typename MemType, typename PtrType>
151{
152 template <typename Object>
153 bool operator() (Object &&obj) const {
154 Op op;
155 return op(std::invoke(ptr, std::forward<Object>(obj)), value);
156 }
157
158 PtrType ptr;
159 const MemType value;
160};
161
162template<typename Op, typename Class, typename MemType, typename PtrType>
164{
165 template <typename Object>
166 bool operator() (Object &&lhs, Object &&rhs) const {
167 Op op;
168 return op(std::invoke(ptr, std::forward<Object>(lhs)),
169 std::invoke(ptr, std::forward<Object>(rhs)));
170 }
171
172 template <typename Object>
173 bool operator() (Object &&lhs, const MemType &rhs) const {
174 Op op;
175 return op(std::invoke(ptr, std::forward<Object>(lhs)),
176 rhs);
177 }
178
179 template <typename Object>
180 bool operator() (const MemType &lhs, Object &&rhs) const {
181 Op op;
182 return op(lhs,
183 std::invoke(ptr, std::forward<Object>(rhs)));
184 }
185
186 PtrType ptr;
187};
188
189} // detail
190
232template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
233inline auto mem_equal_to(MemTypeNoRef Class::*ptr, MemType &&value) {
234 return detail::mem_checker<std::equal_to<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
235}
236
237// non-const member function
238template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
239inline auto mem_equal_to(MemTypeNoRef (Class::*ptr)(), MemType &&value) {
240 return detail::mem_checker<std::equal_to<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
241}
242
243// const member function
244template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
245inline auto mem_equal_to(MemTypeNoRef (Class::*ptr)() const, MemType &&value) {
246 return detail::mem_checker<std::equal_to<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
247}
248
249// non-const noexcept member function
250template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
251inline auto mem_equal_to(MemTypeNoRef (Class::*ptr)() noexcept, MemType &&value) {
252 return detail::mem_checker<std::equal_to<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
253}
254
255// const noexcept member function
256template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
257inline auto mem_equal_to(MemTypeNoRef (Class::*ptr)() const noexcept, MemType &&value) {
258 return detail::mem_checker<std::equal_to<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
259}
260
268template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
269inline auto mem_less(MemTypeNoRef Class::*ptr, MemType &&value) {
270 return detail::mem_checker<std::less<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
271}
272
273// non-const member function
274template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
275inline auto mem_less(MemTypeNoRef (Class::*ptr)(), MemType &&value) {
276 return detail::mem_checker<std::less<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
277}
278
279// const member function
280template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
281inline auto mem_less(MemTypeNoRef (Class::*ptr)() const, MemType &&value) {
282 return detail::mem_checker<std::less<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
283}
284
285// non-const noexcept member function
286template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
287inline auto mem_less(MemTypeNoRef (Class::*ptr)() noexcept, MemType &&value) {
288 return detail::mem_checker<std::less<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
289}
290
291// const noexcept member function
292template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
293inline auto mem_less(MemTypeNoRef (Class::*ptr)() const noexcept, MemType &&value) {
294 return detail::mem_checker<std::less<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
295}
296
304template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
305inline auto mem_less_equal(MemTypeNoRef Class::*ptr, MemType &&value) {
306 return detail::mem_checker<std::less_equal<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
307}
308
309// non-const member function
310template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
311inline auto mem_less_equal(MemTypeNoRef (Class::*ptr)(), MemType &&value) {
312 return detail::mem_checker<std::less_equal<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
313}
314
315// const member function
316template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
317inline auto mem_less_equal(MemTypeNoRef (Class::*ptr)() const, MemType &&value) {
318 return detail::mem_checker<std::less_equal<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
319}
320
321// non-const noexcept member function
322template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
323inline auto mem_less_equal(MemTypeNoRef (Class::*ptr)() noexcept, MemType &&value) {
324 return detail::mem_checker<std::less_equal<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
325}
326
327// const noexcept member function
328template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
329inline auto mem_less_equal(MemTypeNoRef (Class::*ptr)() const noexcept, MemType &&value) {
330 return detail::mem_checker<std::less_equal<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
331}
332
340template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
341inline auto mem_greater(MemTypeNoRef Class::*ptr, MemType &&value) {
342 return detail::mem_checker<std::greater<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
343}
344
345// non-const member function
346template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
347inline auto mem_greater(MemTypeNoRef (Class::*ptr)(), MemType &&value) {
348 return detail::mem_checker<std::greater<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
349}
350
351// const member function
352template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
353inline auto mem_greater(MemTypeNoRef (Class::*ptr)() const, MemType &&value) {
354 return detail::mem_checker<std::greater<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
355}
356
357// non-const noexcept member function
358template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
359inline auto mem_greater(MemTypeNoRef (Class::*ptr)() noexcept, MemType &&value) {
360 return detail::mem_checker<std::greater<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
361}
362
363// const noexcept member function
364template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
365inline auto mem_greater(MemTypeNoRef (Class::*ptr)() const noexcept, MemType &&value) {
366 return detail::mem_checker<std::greater<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
367}
368
377template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
378inline auto mem_greater_equal(MemTypeNoRef Class::*ptr, MemType &&value) {
379 return detail::mem_checker<std::greater_equal<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
380}
381
382// non-const member function
383template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
384inline auto mem_greater_equal(MemTypeNoRef (Class::*ptr)(), MemType &&value) {
385 return detail::mem_checker<std::greater_equal<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
386}
387
388// const member function
389template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
390inline auto mem_greater_equal(MemTypeNoRef (Class::*ptr)() const, MemType &&value) {
391 return detail::mem_checker<std::greater_equal<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
392}
393
394// non-const noexcept member function
395template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
396inline auto mem_greater_equal(MemTypeNoRef (Class::*ptr)() noexcept, MemType &&value) {
397 return detail::mem_checker<std::greater_equal<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
398}
399
400// const noexcept member function
401template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
402inline auto mem_greater_equal(MemTypeNoRef (Class::*ptr)() const noexcept, MemType &&value) {
403 return detail::mem_checker<std::greater_equal<>, Class, MemTypeNoRef, decltype(ptr)>{ptr, std::forward<MemType>(value)};
404}
405
447template<typename Class, typename MemType>
448inline auto mem_less(MemType Class::*ptr) {
449 return detail::mem_compare<std::less<>, Class, MemType, decltype(ptr)>{ptr};
450}
451
452// non-const member function
453template<typename Class, typename MemType>
454inline auto mem_less(MemType (Class::*ptr)()) {
455 return detail::mem_compare<std::less<>, Class, MemType, decltype(ptr)>{ptr};
456}
457
458// const member function
459template<typename Class, typename MemType>
460inline auto mem_less(MemType (Class::*ptr)() const) {
461 return detail::mem_compare<std::less<>, Class, MemType, decltype(ptr)>{ptr};
462}
463
464// non-const noexcept member function
465template<typename Class, typename MemType>
466inline auto mem_less(MemType (Class::*ptr)() noexcept) {
467 return detail::mem_compare<std::less<>, Class, MemType, decltype(ptr)>{ptr};
468}
469
470// const noexcept member function
471template<typename Class, typename MemType>
472inline auto mem_less(MemType (Class::*ptr)() const noexcept) {
473 return detail::mem_compare<std::less<>, Class, MemType, decltype(ptr)>{ptr};
474}
475
482template<typename Class, typename MemType>
483inline auto mem_less_equal(MemType Class::*ptr) {
484 return detail::mem_compare<std::less_equal<>, Class, MemType, decltype(ptr)>{ptr};
485}
486
487// non-const member function
488template<typename Class, typename MemType>
489inline auto mem_less_equal(MemType (Class::*ptr)()) {
490 return detail::mem_compare<std::less_equal<>, Class, MemType, decltype(ptr)>{ptr};
491}
492
493// const member function
494template<typename Class, typename MemType>
495inline auto mem_less_equal(MemType (Class::*ptr)() const) {
496 return detail::mem_compare<std::less_equal<>, Class, MemType, decltype(ptr)>{ptr};
497}
498
499// non-const noexcept member function
500template<typename Class, typename MemType>
501inline auto mem_less_equal(MemType (Class::*ptr)() noexcept) {
502 return detail::mem_compare<std::less_equal<>, Class, MemType, decltype(ptr)>{ptr};
503}
504
505// const noexcept member function
506template<typename Class, typename MemType>
507inline auto mem_less_equal(MemType (Class::*ptr)() const noexcept) {
508 return detail::mem_compare<std::less_equal<>, Class, MemType, decltype(ptr)>{ptr};
509}
510
518template<typename Class, typename MemType>
519inline auto mem_greater(MemType Class::*ptr) {
520 return detail::mem_compare<std::greater<>, Class, MemType, decltype(ptr)>{ptr};
521}
522
523// non-const member function
524template<typename Class, typename MemType>
525inline auto mem_greater(MemType (Class::*ptr)()) {
526 return detail::mem_compare<std::greater<>, Class, MemType, decltype(ptr)>{ptr};
527}
528
529// const member function
530template<typename Class, typename MemType>
531inline auto mem_greater(MemType (Class::*ptr)() const) {
532 return detail::mem_compare<std::greater<>, Class, MemType, decltype(ptr)>{ptr};
533}
534
535// non-const noexcept member function
536template<typename Class, typename MemType>
537inline auto mem_greater(MemType (Class::*ptr)() noexcept) {
538 return detail::mem_compare<std::greater<>, Class, MemType, decltype(ptr)>{ptr};
539}
540
541// const noexcept member function
542template<typename Class, typename MemType>
543inline auto mem_greater(MemType (Class::*ptr)() const noexcept) {
544 return detail::mem_compare<std::greater<>, Class, MemType, decltype(ptr)>{ptr};
545}
546
554template<typename Class, typename MemType>
555inline auto mem_greater_equal(MemType Class::*ptr) {
556 return detail::mem_compare<std::greater_equal<>, Class, MemType, decltype(ptr)>{ptr};
557}
558
559// non-const member function
560template<typename Class, typename MemType>
561inline auto mem_greater_equal(MemType (Class::*ptr)()) {
562 return detail::mem_compare<std::greater_equal<>, Class, MemType, decltype(ptr)>{ptr};
563}
564
565// const member function
566template<typename Class, typename MemType>
567inline auto mem_greater_equal(MemType (Class::*ptr)() const) {
568 return detail::mem_compare<std::greater_equal<>, Class, MemType, decltype(ptr)>{ptr};
569}
570
571// non-const noexcept member function
572template<typename Class, typename MemType>
573inline auto mem_greater_equal(MemType (Class::*ptr)() noexcept) {
574 return detail::mem_compare<std::greater_equal<>, Class, MemType, decltype(ptr)>{ptr};
575}
576
577// const noexcept member function
578template<typename Class, typename MemType>
579inline auto mem_greater_equal(MemType (Class::*ptr)() const noexcept) {
580 return detail::mem_compare<std::greater_equal<>, Class, MemType, decltype(ptr)>{ptr};
581}
582
588template <typename F>
589struct finally {
590 finally(F &&f)
591 : m_f(std::forward<F>(f))
592 {
593 }
594
595 finally(const finally &) = delete;
596 finally(finally &&) = delete;
597
599 m_f();
600 }
601private:
603};
604
605
606} // namespace kismpl
607
608#endif // KISMPL_H
float value(const T *src, size_t ch)
auto apply_to_tuple_impl(F f, Tuple &&t, std::index_sequence< I... >)
Definition KisMpl.h:50
std::optional< T > fold_optional(Fun &&fun, Args &&...args)
Definition KisMpl.h:137
auto mem_equal_to(MemTypeNoRef Class::*ptr, MemType &&value)
mem_equal_to is an unary functor that compares a member of the object to a given value
Definition KisMpl.h:233
auto mem_greater(MemTypeNoRef Class::*ptr, MemType &&value)
mem_greater is an unary functor that compares a member of the object to a given value
Definition KisMpl.h:341
auto apply_to_tuple(F f, Tuple &&t)
Definition KisMpl.h:60
auto mem_greater_equal(MemTypeNoRef Class::*ptr, MemType &&value)
mem_greater_equal is an unary functor that compares a member of the object to a given value
Definition KisMpl.h:378
overloaded(Ts...) -> overloaded< Ts... >
auto mem_less_equal(MemTypeNoRef Class::*ptr, MemType &&value)
mem_less_equal is an unary functor that compares a member of the object to a given value
Definition KisMpl.h:305
auto mem_less(MemTypeNoRef Class::*ptr, MemType &&value)
mem_less is an unary functor that compares a member of the object to a given value
Definition KisMpl.h:269
constexpr auto unzip_wrapper
Definition KisMpl.h:70
typename detail::make_index_sequence_from_1_impl< Num >::type make_index_sequence_from_1
Definition KisMpl.h:44
typename first_type< T... >::type first_type_t
Definition KisMpl.h:101
std::optional< T > fold(const std::optional< T > &first)
Definition KisMpl.h:106
std::optional< T > fold(const std::optional< T > &first, const std::optional< T > &second)
Definition KisMpl.h:110
std::optional< T > fold(const std::optional< T > &first, std::optional< T > const &second, const std::optional< Rest > &...rest)
Definition KisMpl.h:121
typename make_index_sequence_from_1_impl< num - 1, num, Idx... >::type type
Definition KisMpl.h:27
bool operator()(Object &&obj) const
Definition KisMpl.h:153
bool operator()(Object &&lhs, Object &&rhs) const
Definition KisMpl.h:166
typename detail::first_type_impl< T... >::type type
Definition KisMpl.h:93