xtd 1.0.0
Loading...
Searching...
No Matches
delegate.hpp
Go to the documentation of this file.
1
4#pragma once
5#include "any.hpp"
7#include "async_result.hpp"
8#include "iequatable.hpp"
9#include "object.hpp"
10#include "object_ref.hpp"
11#include "usize.hpp"
12#include <functional>
13#include <vector>
14
16namespace xtd {
18 template<typename result_t>
19 class delegate;
20
21 template<typename result_t, typename ...arguments_t>
22 class delegate<result_t(arguments_t...)>;
24
39 using async_callback = xtd::delegate<void(async_result ar)>;
40
55 template<typename result_t>
56 class delegate<result_t()> : public xtd::object, public xtd::iequatable<delegate<result_t()>> {
57 struct data {
58 std::vector<std::function<result_t()>> functions;
59 };
60
61 class async_result_invoke : public xtd::iasync_result {
62 struct data;
63 public:
64 async_result_invoke(xtd::async_callback async_callback, const xtd::any_object& async_state);
65 [[nodiscard]] auto async_state() const noexcept -> xtd::any_object override;
66 [[nodiscard]] auto async_wait_handle() noexcept -> xtd::threading::wait_handle& override;
67 [[nodiscard]] auto completed_synchronously() const noexcept -> bool override;
68 [[nodiscard]] auto is_completed() const noexcept -> bool override;
69
70 xtd::sptr<data> data_;
71 };
72
73 public:
75
78 using function_t = std::function<result_t()>;
80 using function_collection = std::vector<function_t>;
82
84
87 delegate() = default;
89 delegate(delegate&&) = default;
90 delegate(const delegate& other) {*data_ = *other.data_;}
91 delegate& operator =(const delegate& other) {*data_ = *other.data_; return *this;}
92
93 template <typename fct_t>
95 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
96 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
97 std::invocable<fct_t&> &&
98 std::convertible_to<std::invoke_result_t<fct_t&>, result_t>
99 delegate(fct_t&& f) {data_->functions.push_back(function_t(std::forward<fct_t>(f)));}
101
104 delegate(const function_t& function) noexcept {data_->functions.push_back(function);} // Can't be explicit by design.
105
109 template<class object1_t, typename object2_t>
110 delegate(const object1_t& object, result_t(object2_t::*method)() const) noexcept {data_->functions.push_back(function_t(std::bind(method, const_cast<object1_t*>(&object))));}
114 template<class object1_t, typename object2_t>
115 delegate(const object1_t& object, result_t(object2_t::*method)()) noexcept {data_->functions.push_back(function_t(std::bind(method, const_cast<object1_t*>(&object))));}
117
119
123 [[nodiscard]] auto count() const noexcept -> xtd::usize {return data_->functions.size();}
124
127 [[nodiscard]] auto functions() const -> const function_collection& {return data_->functions;}
128
131 [[nodiscard]] auto is_empty() const noexcept -> bool {return count() == 0;}
132
135 [[nodiscard]] auto size() const noexcept -> xtd::usize {return count();}
137
139
142 auto clear() -> void {data_->functions.clear();}
143
149 [[nodiscard]] auto begin_invoke() -> async_result;
165
171 auto end_invoke(async_result async) -> result_t;
172
179 auto invoke() const -> result_t {return operator()();}
180
184 [[nodiscard]] auto equals(const object& obj) const noexcept -> bool override {return is<delegate>(obj) && equals(static_cast<const delegate&>(obj));}
188 [[nodiscard]] auto equals(const delegate& other) const noexcept -> bool override {
189 if (data_->functions.size() != other.data_->functions.size()) return false;
190 for (auto i = xtd::usize {0}; i < data_->functions.size(); i++)
191 if (!are_equals(data_->functions[i], other.data_->functions[i])) return false;
192 return true;
193 }
194
195
197
204 [[nodiscard]] static auto combine(const xtd::array<delegate>& delegates) noexcept -> delegate {
205 auto result = delegate {};
206 for (auto delegate : delegates)
207 for (auto function : delegate.data_->functions)
208 result.data_->functions.push_back(function);
209 return result;
210 }
211
217 [[nodiscard]] static auto combine(const delegate& a, const delegate& b) noexcept -> delegate {return combine({a, b});}
218
224 [[nodiscard]] static auto remove(const delegate& source, const delegate& value) noexcept -> delegate {
225 auto result = source;
226 std::for_each(value.data_->functions.begin(), value.data_->functions.end(), [&](const auto& function) {
227 auto iterator = std::find_if(result.data_->functions.rbegin(), result.data_->functions.rend(), [&](const auto& item) {return are_equals(item, function);});
228 if (iterator != result.data_->functions.rend()) result.data_->functions.erase((iterator + 1).base());
229 });
230 return result;
231 }
232
238 [[nodiscard]] static auto remove_all(const delegate& source, const delegate& value) noexcept -> delegate {
239 delegate result = source;
240 for (const function_t& function : value.data_->functions) {
241 if (find(result.data_->functions.begin(), result.data_->functions.end(), function) != result.data_->functions.end()) {
242 for (typename function_collection::reverse_iterator iterator = result.data_->functions.rbegin(); iterator != result.data_->functions.rend(); ++iterator) {
243 if (are_equals(*iterator, function))
244 result.data_->functions.erase((iterator + 1).base());
245 }
246 }
247 }
248 return result;
249 }
250
251
253
258 auto operator()() const -> result_t {
259 if (data_->functions.size() == 0) {
260 if constexpr(std::is_void_v<result_t>) return;
261 else if constexpr(std::is_reference_v<result_t>) {
262 using underlying_t = std::remove_reference_t<result_t>;
263 if constexpr(std::is_const_v<underlying_t>) {
264 static const underlying_t empty_value{};
265 return empty_value;
266 } else {
267 static underlying_t empty_value{};
268 return empty_value;
269 }
270 } else return result_t{};
271 }
272
273 for (auto i = xtd::usize {0}; i < data_->functions.size() - 1; i++) {
275 data_->functions[i]();
276 }
278 return data_->functions.back()();
279 }
280
281 auto operator =(const function_t& function) noexcept -> delegate& {
282 data_->functions.clear();
283 data_->functions.push_back(function);
284 return *this;
285 }
287
289 [[nodiscard]] auto operator +(const delegate& other) const noexcept -> delegate {
290 delegate result = *this;
291 result += other;
292 return result;
293 }
294
295 [[nodiscard]] auto operator +(const function_t& function) const noexcept -> delegate {
296 delegate result = *this;
297 result += function;
298 return result;
299 }
300
301 template<class fn_t>
302 [[nodiscard]] auto operator +(fn_t function) const noexcept -> delegate {
303 delegate result = *this;
304 result += function;
305 return result;
306 }
307
308 auto operator +=(const delegate& other) noexcept -> delegate& {
309 *this = delegate::combine(*this, other);
310 return *this;
311 }
312
313 auto operator +=(const function_t& function) noexcept -> delegate& {
314 *this = delegate::combine(*this, delegate(function));
315 return *this;
316 }
317
318 template<class fn_t>
319 auto operator +=(fn_t function) noexcept -> delegate& {
320 *this = delegate::combine(*this, delegate(function));
321 return *this;
322 }
323
324 [[nodiscard]] auto operator -(const delegate& other) const noexcept -> delegate {
325 delegate result = *this;
326 result -= other;
327 return result;
328 }
329
330 [[nodiscard]] auto operator -(const function_t& function) const noexcept -> delegate {
331 delegate result = *this;
332 result -= function;
333 return result;
334 }
335
336 template<class fn_t>
337 [[nodiscard]] auto operator -(fn_t function) const noexcept -> delegate {
338 delegate result = *this;
339 result -= function;
340 return result;
341 }
342
343 auto operator -=(const delegate& other) noexcept -> delegate& {
344 *this = delegate::remove(*this, other);
345 return *this;
346 }
347
348 auto operator -=(const function_t& function) noexcept -> delegate& {
349 *this = delegate::remove(*this, delegate(function));
350 return *this;
351 }
352
353 template<class fn_t>
354 auto operator -=(fn_t function) noexcept -> delegate& {
355 *this = delegate::remove(*this, delegate(function));
356 return *this;
357 }
359
360 private:
361 [[nodiscard]] static auto are_equals(const std::function<result_t()>& fct1, const std::function<result_t()>& fct2) noexcept -> bool {return fct1.target_type() == fct2.target_type() && (fct1.template target<result_t(*)()>() == fct2.template target<result_t(*)()>() || *fct1.template target<result_t(*)()>() == *fct2.template target<result_t(*)()>());}
362 [[nodiscard]] static auto find(typename function_collection::const_iterator begin, typename function_collection::const_iterator end, const function_t& function) noexcept -> typename function_collection::const_iterator {
363 auto iterator = std::find_if(begin, end, [&](const auto& item) {return are_equals(item, function);});
364 if (iterator != end) return iterator;
365 return end;
366 }
367
369 };
370
385 template<class result_t, typename ...arguments_t>
386 class delegate<result_t(arguments_t...)> : public object, public xtd::iequatable<delegate<result_t(arguments_t...)>> {
387 struct data {
388 std::vector<std::function<result_t()>> no_arguments_functions;
389 std::vector<std::function<result_t(arguments_t...)>> functions;
390 };
391
392 class async_result_invoke : public xtd::iasync_result {
393 struct data;
394 public:
395 async_result_invoke(xtd::async_callback async_callback, const xtd::any_object& async_state);
396 [[nodiscard]] auto async_state() const noexcept -> xtd::any_object override;
397 [[nodiscard]] auto async_wait_handle() noexcept -> xtd::threading::wait_handle& override;
398 [[nodiscard]] auto completed_synchronously() const noexcept -> bool override;
399 [[nodiscard]] auto is_completed() const noexcept -> bool override;
400
401 xtd::sptr<data> data_;
402 };
403
404 public:
406
409 using no_arguments_function_t = std::function<result_t()>;
411 using function_t = std::function<result_t(arguments_t...)>;
413 using no_arguments_function_collection = std::vector<no_arguments_function_t>;
415 using function_collection = std::vector<function_t>;
417
419
422 delegate() = default;
424 delegate(delegate&&) = default;
425 delegate(const delegate& other) {*data_ = *other.data_;}
426 delegate& operator =(const delegate& other) {*data_ = *other.data_; return *this;}
428
431 delegate(const function_t& function) noexcept {data_->functions.push_back(function);} // Can't be explicit by design.
432
436 template<class object1_t, typename object2_t>
437 delegate(const object1_t& object, result_t(object2_t::*method)() const) noexcept {data_->functions.push_back(function_t(std::bind(method, const_cast<object1_t*>(&object))));}
438
442 template<class object1_t, typename object2_t>
443 delegate(const object1_t& object, result_t(object2_t::*method)()) noexcept {data_->functions.push_back(function_t(std::bind(method, const_cast<object1_t*>(&object))));}
445
447 template<class object1_t, typename object2_t, typename... args_t>
448 delegate(const object1_t& object, result_t(object2_t::*method)(args_t...) const) noexcept {data_->functions.push_back(function_t(std::bind_front(method, const_cast<object1_t*>(&object))));}
449
450 template<class object1_t, typename object2_t, typename... args_t>
451 delegate(const object1_t& object, result_t(object2_t::*method)(args_t...)) noexcept {data_->functions.push_back(function_t(std::bind_front(method, const_cast<object1_t*>(&object))));}
452
453 template <typename fct_t>
454 requires (!xtd::expressions::expression_operand<fct_t>) &&
455 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
456 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
457 std::invocable<fct_t&, arguments_t...>
458 delegate(fct_t&& f) {data_->functions.push_back(function_t(std::forward<fct_t>(f)));}
459
460 template <typename fct_t>
461 requires (!xtd::expressions::expression_operand<fct_t>) &&
462 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
463 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
464 std::invocable<fct_t&>
465 delegate(fct_t&& f) {data_->no_arguments_functions.push_back(no_arguments_function_t(std::forward<fct_t>(f)));}
466
467 template <typename expression_t>
468 requires xtd::expressions::expression_operand<expression_t> &&
469 requires (expression_t e, arguments_t... args) { { e(args...) } -> std::convertible_to<result_t>;}
470 delegate(expression_t&& expression) {data_->functions.push_back(function_t(std::forward<expression_t>(expression)));}
472
474
478 [[nodiscard]] auto count() const noexcept -> xtd::usize {return data_->functions.size() + data_->no_arguments_functions.size();}
479
482 [[nodiscard]] auto no_arguments_functions() const -> const no_arguments_function_collection& {return data_->no_arguments_functions;}
483
486 [[nodiscard]] auto functions() const -> const function_collection& {return data_->functions;}
487
490 [[nodiscard]] auto is_empty() const noexcept -> bool {return count() == 0;}
491
494 [[nodiscard]] auto size() const noexcept -> xtd::usize {return count();}
496
498
508 [[nodiscard]] auto begin_invoke(arguments_t&&... arguments) -> async_result;
516 [[nodiscard]] auto begin_invoke(xtd::async_callback async_callback, arguments_t&&... arguments) -> async_result;
523 [[nodiscard]] auto begin_invoke(xtd::async_callback async_callback, const xtd::any_object& async_state, arguments_t&&... arguments) -> async_result;
524
530 auto end_invoke(async_result async) -> result_t;
531
538 auto invoke(arguments_t&&... arguments) const -> result_t {return operator()(arguments...);}
539
543 [[nodiscard]] auto equals(const object& obj) const noexcept -> bool override {return is<delegate>(obj) && equals(static_cast<const delegate&>(obj));}
547 [[nodiscard]] auto equals(const delegate& other) const noexcept -> bool override {
548 if (data_->functions.size() != other.data_->functions.size() || data_->no_arguments_functions.size() != other.data_->no_arguments_functions.size()) return false;
549 for (auto i = xtd::usize {0}; i < data_->no_arguments_functions.size(); i++)
550 if (!are_equals(data_->no_arguments_functions[i], other.data_->no_arguments_functions[i])) return false;
551 for (auto i = xtd::usize {0}; i < data_->functions.size(); i++)
552 if (!are_equals(data_->functions[i], other.data_->functions[i])) return false;
553 return true;
554 }
555
556
558
565 [[nodiscard]] static auto combine(const xtd::array<delegate>& delegates) noexcept -> delegate {
566 auto result = delegate {};
567 for (auto delegate : delegates) {
568 for (auto function : delegate.data_->no_arguments_functions)
569 result.data_->no_arguments_functions.push_back(function);
570 for (auto function : delegate.data_->functions)
571 result.data_->functions.push_back(function);
572 }
573 return result;
574 }
575
581 [[nodiscard]] static auto combine(const delegate& a, const delegate& b) noexcept -> delegate {return combine({a, b});}
582
588 [[nodiscard]] static auto remove(const delegate& source, const delegate& value) noexcept -> delegate {
589 auto result = source;
590 std::for_each(value.data_->no_arguments_functions.begin(), value.data_->no_arguments_functions.end(), [&](const auto& no_arguments_function) {
591 auto iterator = std::find_if(result.data_->no_arguments_functions.rbegin(), result.data_->no_arguments_functions.rend(), [&](const auto& item) {return are_equals(item, no_arguments_function);});
592 if (iterator != result.data_->no_arguments_functions.rend()) result.data_->no_arguments_functions.erase((iterator + 1).base());
593 });
594
595 std::for_each(value.data_->functions.begin(), value.data_->functions.end(), [&](const auto& function) {
596 auto iterator = std::find_if(result.data_->functions.rbegin(), result.data_->functions.rend(), [&](const auto& item) {return are_equals(item, function);});
597 if (iterator != result.data_->functions.rend()) result.data_->functions.erase((iterator + 1).base());
598 });
599 return result;
600 }
601
607 [[nodiscard]] static auto remove_all(const delegate& source, const delegate& value) noexcept -> delegate {
608 auto result = source;
609 for (auto function : value.data_->no_arguments_functions) {
610 if (find(result.data_->no_arguments_functions.begin(), result.data_->no_arguments_functions.end(), function) != result.data_->no_arguments_functions.end()) {
611 for (typename function_collection::reverse_iterator iterator = result.data_->no_arguments_functions.rbegin(); iterator != result.data_->no_arguments_functions.rend(); ++iterator) {
612 if (are_equals(*iterator, function))
613 result.data_->no_arguments_functions.erase((iterator + 1).base());
614 }
615 }
616 }
617
618 for (auto function : value.data_->functions) {
619 if (find(result.data_->functions.begin(), result.data_->functions.end(), function) != result.data_->functions.end()) {
620 for (auto iterator = result.data_->functions.rbegin(); iterator != result.data_->functions.rend(); ++iterator) {
621 if (are_equals(*iterator, function))
622 result.data_->functions.erase((iterator + 1).base());
623 }
624 }
625 }
626 return result;
627 }
628
629
631
636 auto operator()(arguments_t... arguments) const -> result_t {
637 if (data_->no_arguments_functions.size() == 0 && data_->functions.size() == 0) {
638 if constexpr(std::is_void_v<result_t>) return;
639 else if constexpr(std::is_reference_v<result_t>) {
640 using underlying_t = std::remove_reference_t<result_t>;
641 if constexpr(std::is_const_v<underlying_t>) {
642 static const underlying_t empty_value{};
643 return empty_value;
644 } else {
645 static underlying_t empty_value{};
646 return empty_value;
647 }
648 } else return result_t{};
649 }
650
651 if (data_->no_arguments_functions.size()) {
652 for (auto i = xtd::usize {0}; i < data_->no_arguments_functions.size() - (data_->functions.size() == 0 ? 1 : 0); i++) {
653 if (data_->no_arguments_functions[i] == nullptr) xtd::helpers::throw_helper::throws(xtd::helpers::exception_case::argument_null);
654 data_->no_arguments_functions[i]();
655 }
656
657 if (data_->functions.size() == 0) {
658 if (data_->no_arguments_functions.back() == nullptr) xtd::helpers::throw_helper::throws(xtd::helpers::exception_case::argument_null);
659 return data_->no_arguments_functions.back()();
660 }
661 }
662
663 for (auto i = xtd::usize {0}; i < data_->functions.size() - 1; i++) {
665 data_->functions[i](arguments...);
666 }
668 return data_->functions.back()(arguments...);
669 }
670
671
673 template <typename fct_t>
675 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
676 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
677 std::invocable<fct_t&, arguments_t...>
678 auto operator =(fct_t&& function) noexcept -> delegate& {
679 data_->no_arguments_functions.clear();
680 data_->functions.clear();
681 data_->functions.push_back(function_t(function));
682 return *this;
683 }
684
685 template <typename fct_t>
687 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
688 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
689 std::invocable<fct_t&>
690 auto operator =(fct_t&& function) noexcept -> delegate& {
691 data_->no_arguments_functions.clear();
692 data_->functions.clear();
693 data_->no_arguments_functions.push_back(no_arguments_function_t(function));
694 return *this;
695 }
696
697 template <typename expression_t>
699 requires (expression_t e, arguments_t... args) { { e(args...) } -> std::convertible_to<result_t>;}
700 auto operator =(expression_t&& expression) noexcept -> delegate& {
701 data_->no_arguments_functions.clear();
702 data_->functions.clear();
703 data_->functions.push_back(function_t(expression));
704 return *this;
705 }
706
707 auto operator =(const function_t& function) noexcept -> delegate& {
708 data_->no_arguments_functions.clear();
709 data_->functions.clear();
710 data_->functions.push_back(function);
711 return *this;
712 }
713
714 [[nodiscard]] auto operator +(const delegate& other) const noexcept -> delegate {
715 delegate result = *this;
716 result += other;
717 return result;
718 }
719
720 [[nodiscard]] auto operator +(const function_t& function) const noexcept -> delegate {
721 delegate result = *this;
722 result += function;
723 return result;
724 }
725
726 template <typename fct_t>
728 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
729 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
730 std::invocable<fct_t&, arguments_t...>
731 [[nodiscard]] auto operator +(fct_t&& function) noexcept -> delegate {
732 delegate result = *this;
733 result += function;
734 return result;
735 }
736
737 template <typename fct_t>
739 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
740 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
741 std::invocable<fct_t&>
742 [[nodiscard]] auto operator +(fct_t&& function) noexcept -> delegate {
743 delegate result = *this;
744 result += function;
745 return result;
746 }
747
748 template <typename expression_t>
750 requires (expression_t e, arguments_t... args) { { e(args...) } -> std::convertible_to<result_t>;}
751 [[nodiscard]] auto operator +(expression_t&& expression) noexcept -> delegate {
752 delegate result = *this;
753 result += expression;
754 return result;
755 }
756
757 auto operator +=(const delegate& other) noexcept -> delegate& {
758 *this = delegate::combine(*this, other);
759 return *this;
760 }
761
762 auto operator +=(const function_t& function) noexcept -> delegate& {
763 *this = delegate::combine(*this, delegate(function));
764 return *this;
765 }
766
767 template <typename fct_t>
769 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
770 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
771 std::invocable<fct_t&, arguments_t...>
772 auto operator +=(fct_t&& function) noexcept -> delegate& {
773 *this = delegate::combine(*this, delegate(function));
774 return *this;
775 }
776
777 template <typename fct_t>
779 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
780 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
781 std::invocable<fct_t&>
782 auto operator +=(fct_t&& function) noexcept -> delegate& {
783 *this = delegate::combine(*this, delegate(function));
784 return *this;
785 }
786
787 template <typename expression_t>
789 requires (expression_t e, arguments_t... args) { { e(args...) } -> std::convertible_to<result_t>;}
790 auto operator +=(expression_t&& expression) noexcept -> delegate& {
791 *this = delegate::combine(*this, delegate(expression));
792 return *this;
793 }
794
795 [[nodiscard]] auto operator -(const delegate& other) const noexcept -> delegate {
796 delegate result = *this;
797 result -= other;
798 return result;
799 }
800
801 [[nodiscard]] auto operator -(const function_t& function) const noexcept -> delegate {
802 delegate result = *this;
803 result -= function;
804 return result;
805 }
806
807 template <typename fct_t>
809 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
810 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
811 std::invocable<fct_t&, arguments_t...>
812 [[nodiscard]] auto operator -(fct_t&& function) noexcept -> delegate {
813 delegate result = *this;
814 result -= function;
815 return result;
816 }
817
818 template <typename fct_t>
820 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
821 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
822 std::invocable<fct_t&>
823 [[nodiscard]] auto operator -(fct_t&& function) noexcept -> delegate {
824 delegate result = *this;
825 result -= function;
826 return result;
827 }
828
829 template <typename expression_t>
831 requires (expression_t e, arguments_t... args) { { e(args...) } -> std::convertible_to<result_t>;}
832 [[nodiscard]] auto operator -(expression_t&& expression) noexcept -> delegate {
833 delegate result = *this;
834 result -= expression;
835 return result;
836 }
837
838 auto operator -=(const delegate& other) noexcept -> delegate& {
839 *this = delegate::remove(*this, other);
840 return *this;
841 }
842
843 auto operator -=(const function_t& function) noexcept -> delegate& {
844 *this = delegate::remove(*this, delegate(function));
845 return *this;
846 }
847
848 template <typename fct_t>
850 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
851 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
852 std::invocable<fct_t&, arguments_t...>
853 auto operator -=(fct_t&& function) noexcept -> delegate& {
854 *this = delegate::remove(*this, delegate(function));
855 return *this;
856 }
857
858 template <typename fct_t>
860 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
861 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
862 std::invocable<fct_t&>
863 auto operator -=(fct_t&& function) noexcept -> delegate& {
864 *this = delegate::remove(*this, delegate(function));
865 return *this;
866 }
867
868 template <typename expression_t>
870 requires (expression_t e, arguments_t... args) { { e(args...) } -> std::convertible_to<result_t>;}
871 auto operator -=(expression_t&& expression) noexcept -> delegate& {
872 *this = delegate::remove(*this, delegate(expression));
873 return *this;
874 }
876
877 private:
878 struct delegate_async_state;
879
880 [[nodiscard]] static auto are_equals(const std::function<result_t(arguments_t...)>& fct1, const std::function<result_t(arguments_t...)>& fct2) noexcept -> bool {
881 return fct1.target_type() == fct2.target_type() && (fct1.template target<result_t(*)(arguments_t...)>() == fct2.template target<result_t(*)(arguments_t...)>() || *fct1.template target<result_t(*)(arguments_t...)>() == *fct2.template target<result_t(*)(arguments_t...)>());
882 }
883
884 [[nodiscard]] static auto are_equals(const std::function<result_t()>& fct1, const std::function<result_t()>& fct2) noexcept -> bool {
885 return fct1.target_type() == fct2.target_type() && (fct1.template target<result_t(*)()>() == fct2.template target<result_t(*)()>() || *fct1.template target<result_t(*)()>() == *fct2.template target<result_t(*)()>());
886 }
887
888 [[nodiscard]] static auto find(typename no_arguments_function_collection::const_iterator begin, typename no_arguments_function_collection::const_iterator end, const no_arguments_function_t& function) noexcept -> typename no_arguments_function_collection::const_iterator {
889 auto iterator = std::find_if(begin, end, [&](const auto& item) {return are_equals(item, function);});
890 if (iterator != end) return iterator;
891 return end;
892 }
893
894 [[nodiscard]] static auto find(typename function_collection::const_iterator begin, typename function_collection::const_iterator end, const function_t& function) noexcept -> typename function_collection::const_iterator {
895 auto iterator = std::find_if(begin, end, [&](const auto& item) {return are_equals(item, function);});
896 if (iterator != end) return iterator;
897 return end;
898 }
899
901 };
902
904 // Deduction guides for xtd::delegate
905 // {
906 template<typename>
907 struct function_traits;
908
909 template<typename result_t, typename... args_t>
910 struct function_traits<result_t(args_t...)> {using signature = result_t(args_t...);};
911
912 template<typename result_t, typename... args_t>
913 struct function_traits<result_t(*)(args_t...)> : function_traits<result_t(args_t...)> {};
914
915 template<typename class_t, typename result_t, typename... args_t>
916 struct function_traits<result_t(class_t::*)(args_t...) const> : function_traits<result_t(args_t...)> {};
917
918 template<typename type_t>
919 struct function_traits : function_traits<decltype(&type_t::operator())> {};
920
921 template<typename function_t>
922 delegate(function_t) -> delegate<typename function_traits<function_t>::signature>;
923
924 template<typename result_t, typename... args_t>
925 delegate(std::function<result_t(args_t...)>) -> delegate<result_t(args_t...)>;
926 // }
928}
929
942#define delegate_ \
943 [&]
944
945// Required for begin_invoke and end_invoke methods implementation.
Contains xtd::any type and std::bad_any_cast exception.
Contains xtd::async_result alias.
Represent a polymorphic wrapper capable of holding any type.
Definition any_object.hpp:29
Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the ba...
Definition array.hpp:64
auto end_invoke(async_result async) -> result_t
Retrieves the return value of the asynchronous operation represented by the async_result_invoke passe...
static auto remove(const delegate &source, const delegate &value) noexcept -> delegate
removes the last occurrence of the invocation list of a delegate from the invocation list of another ...
Definition delegate.hpp:224
static auto combine(const delegate &a, const delegate &b) noexcept -> delegate
Concatenates the invocation lists of two delegates.
Definition delegate.hpp:217
auto begin_invoke(xtd::async_callback async_callback, const xtd::any_object &async_state) -> async_result
Executes the method represented by the current delegate asynchronously on the thread that the control...
auto operator()() const -> result_t
invokes the method represented by the current delegate.
Definition delegate.hpp:258
delegate(const object1_t &object, result_t(object2_t::*method)()) noexcept
Initializes a delegate that invokes the specified instance method on the specified class instance.
Definition delegate.hpp:115
auto begin_invoke() -> async_result
Executes the method represented by the current delegate asynchronously on the thread that the control...
std::vector< function_t > function_collection
Represents the function collection type.
Definition delegate.hpp:80
auto functions() const -> const function_collection &
Gets the delegates array.
Definition delegate.hpp:127
static auto remove_all(const delegate &source, const delegate &value) noexcept -> delegate
removes all occurrences of the invocation list of a delegate from the invocation list of another dele...
Definition delegate.hpp:238
delegate(const object1_t &object, result_t(object2_t::*method)() const) noexcept
Initializes a delegate that invokes the specified instance method on the specified class instance.
Definition delegate.hpp:110
auto equals(const object &obj) const noexcept -> bool override
Determines whether this instance and another specified delegateType object have the same value.
Definition delegate.hpp:184
auto equals(const delegate &other) const noexcept -> bool override
Determines whether this instance and another specified delegateType object have the same value.
Definition delegate.hpp:188
delegate()=default
Initializes an empty delegate.
auto clear() -> void
Clear delegates array.
Definition delegate.hpp:142
auto is_empty() const noexcept -> bool
Return if the delegate is empty.
Definition delegate.hpp:131
auto begin_invoke(xtd::async_callback async_callback) -> async_result
Executes the method represented by the current delegate asynchronously on the thread that the control...
delegate(const function_t &function) noexcept
Initializes a delegate that invokes the specified instance method.
Definition delegate.hpp:104
auto count() const noexcept -> xtd::usize
Return the size of invocation list.
Definition delegate.hpp:123
static auto combine(const xtd::array< delegate > &delegates) noexcept -> delegate
Concatenates the invocation lists of an array of delegates.
Definition delegate.hpp:204
auto size() const noexcept -> xtd::usize
Return the size of invocation list.
Definition delegate.hpp:135
std::function< result_t()> function_t
Represents function type.
Definition delegate.hpp:78
auto invoke() const -> result_t
invokes the method represented by the current delegate.
Definition delegate.hpp:179
auto size() const noexcept -> xtd::usize
Return the size of invocation list.
Definition delegate.hpp:494
std::vector< function_t > function_collection
function_t Represents the function collection type.
Definition delegate.hpp:415
auto is_empty() const noexcept -> bool
Return if the delegate is empty.
Definition delegate.hpp:490
auto no_arguments_functions() const -> const no_arguments_function_collection &
Gets the no arguments delegates array.
Definition delegate.hpp:482
delegate()=default
Initializes an empty delegate.
auto begin_invoke(xtd::async_callback async_callback, const xtd::any_object &async_state, arguments_t &&... arguments) -> async_result
Executes the method represented by the current delegate asynchronously on the thread that the control...
static auto remove_all(const delegate &source, const delegate &value) noexcept -> delegate
removes all occurrences of the invocation list of a delegate from the invocation list of another dele...
Definition delegate.hpp:607
auto functions() const -> const function_collection &
Gets the delegates array.
Definition delegate.hpp:486
auto end_invoke(async_result async) -> result_t
Retrieves the return value of the asynchronous operation represented by the async_result_invoke passe...
auto begin_invoke(arguments_t &&... arguments) -> async_result
Executes the method represented by the current delegate asynchronously on the thread that the control...
delegate(const object1_t &object, result_t(object2_t::*method)()) noexcept
Initializes a delegate that invokes the specified instance method on the specified class instance.
Definition delegate.hpp:443
auto equals(const delegate &other) const noexcept -> bool override
Determines whether this instance and another specified delegateType object have the same value.
Definition delegate.hpp:547
static auto remove(const delegate &source, const delegate &value) noexcept -> delegate
removes the last occurrence of the invocation list of a delegate from the invocation list of another ...
Definition delegate.hpp:588
static auto combine(const delegate &a, const delegate &b) noexcept -> delegate
Concatenates the invocation lists of two delegates.
Definition delegate.hpp:581
auto operator()(arguments_t... arguments) const -> result_t
invokes the method represented by the current delegate.
Definition delegate.hpp:636
auto equals(const object &obj) const noexcept -> bool override
Determines whether this instance and another specified delegateType object have the same value.
Definition delegate.hpp:543
std::vector< no_arguments_function_t > no_arguments_function_collection
function_t Represents the no arguments function collection type.
Definition delegate.hpp:413
std::function< result_t(arguments_t...)> function_t
Represents function type.
Definition delegate.hpp:411
static auto combine(const xtd::array< delegate > &delegates) noexcept -> delegate
Concatenates the invocation lists of an array of delegates.
Definition delegate.hpp:565
auto count() const noexcept -> xtd::usize
Return the size of invocation list.
Definition delegate.hpp:478
delegate(const function_t &function) noexcept
Initializes a delegate that invokes the specified instance method.
Definition delegate.hpp:431
auto invoke(arguments_t &&... arguments) const -> result_t
invokes the method represented by the current delegate.
Definition delegate.hpp:538
auto begin_invoke(xtd::async_callback async_callback, arguments_t &&... arguments) -> async_result
Executes the method represented by the current delegate asynchronously on the thread that the control...
std::function< result_t()> no_arguments_function_t
Represents no arguments function type.
Definition delegate.hpp:409
delegate(const object1_t &object, result_t(object2_t::*method)() const) noexcept
Initializes a delegate that invokes the specified instance method on the specified class instance.
Definition delegate.hpp:437
static auto throws(xtd::helpers::exception_case exception_case, const source_location &location=source_location::current()) -> void
Throws an exption with specified exception case.
Represents the status of an asynchronous operation.
Definition iasync_result.hpp:25
Defines a generalized method that a value type or class implements to create a type-specific method f...
Definition iequatable.hpp:23
Supports all classes in the xtd class hierarchy and provides low-level services to derived classes....
Definition object.hpp:45
object()=default
Create a new instance of the ultimate base class object.
Encapsulates operating system specific objects that wait for exclusive access to shared resources.
Definition wait_handle.hpp:52
The xtd::expressions::expression_operand object is expression operand concept.
Definition expression_operand.hpp:27
Contains xtd::expressions::expression_operand concept.
xtd::delegate< void(async_result ar)> async_callback
References a method to be called when a corresponding asynchronous operation completes.
Definition delegate.hpp:39
constexpr auto args()
Generates a set of positional placeholders that can be decomposed using structured bindings to build ...
Definition args.hpp:43
@ argument_null
The argument is null.
Definition exception_case.hpp:33
xtd::shared_ptr_object< type_t > sptr
The xtd::sptr object is a shared pointer.
Definition sptr.hpp:25
std::size_t usize
Represents an unsigned size of any object in bytes.
Definition usize.hpp:22
xtd::sptr< xtd::iasync_result > async_result
Represents the status of an asynchronous operation.
Definition async_result.hpp:19
auto is(xtd::any value) -> bool
Checks if the result of an expression is compatible with a given type.
Definition is.hpp:485
auto new_sptr(args_t &&... args) -> xtd::sptr< type_t >
xtd::new_sptr operator creates a xtd::sptr object.
Definition new_sptr.hpp:24
@ other
The operating system is other.
Definition platform_id.hpp:60
@ a
The A key.
Definition console_key.hpp:88
@ i
The I key.
Definition console_key.hpp:104
@ f
The F key.
Definition console_key.hpp:98
@ b
The B key.
Definition console_key.hpp:90
@ e
The E key.
Definition console_key.hpp:96
@ function
The FUNCTION modifier key.
Definition keys.hpp:480
Contains xtd::iequatable interface.
The xtd namespace contains all fundamental classes to access Hardware, Os, System,...
Definition abstract_object.hpp:8
const xtd::collections::generic::helpers::wrap_pointer_iterator< pointer > iterator
Represents the iterator of read_only_span value type.
Definition read_only_span.hpp:71
auto begin() const -> const_iterator
Returns an iterator to the beginning.
Definition read_only_span.hpp:186
auto end() const -> const_iterator
Returns an iterator to the end.
Definition read_only_span.hpp:205
Contains xtd::object class.
Contains xtd::object_ref alias.
Contains xtd::threading::thread_pool class.
Contains xtd::usize type.