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 for (const auto& function : other.data_->functions)
310 data_->functions.push_back(function);
311 return *this;
312 }
313
314 auto operator +=(delegate&& other) noexcept -> delegate& {
315 for (auto&& function : other.data_->functions)
316 data_->functions.push_back(std::move(function));
317 return *this;
318 }
319
320 auto operator +=(const function_t& function) noexcept -> delegate& {
321 data_->functions.push_back(delagate(function));
322 return *this;
323 }
324
325 template<class fn_t>
326 auto operator +=(fn_t function) noexcept -> delegate& {
327 data_->functions.push_back(delegate(function));
328 return *this;
329 }
330
331 [[nodiscard]] auto operator -(const delegate& other) const noexcept -> delegate {
332 delegate result = *this;
333 result -= other;
334 return result;
335 }
336
337 [[nodiscard]] auto operator -(const function_t& function) const noexcept -> delegate {
338 delegate result = *this;
339 result -= function;
340 return result;
341 }
342
343 template<class fn_t>
344 [[nodiscard]] auto operator -(fn_t function) const noexcept -> delegate {
345 delegate result = *this;
346 result -= function;
347 return result;
348 }
349
350 auto operator -=(const delegate& other) noexcept -> delegate& {
351 std::for_each(other.data_->functions.begin(), other.data_->functions.end(), [&](const auto& function) {
352 auto iterator = std::find_if(data_->functions.rbegin(), data_->functions.rend(), [&](const auto& item) {return are_equals(item, function);});
353 if (iterator != data_->functions.rend()) data_->functions.erase((iterator + 1).base());
354 });
355 return *this;
356 }
357
358 auto operator -=(const function_t& function) noexcept -> delegate& {
359 auto iterator = std::find_if(data_->functions.rbegin(), data_->functions.rend(), [&](const auto& item) {return are_equals(item, function);});
360 if (iterator != data_->functions.rend()) data_->functions.erase((iterator + 1).base());
361 return *this;
362 }
363
364 template<class fn_t>
365 auto operator -=(fn_t function) noexcept -> delegate& {
366 auto iterator = std::find_if(data_->functions.rbegin(), data_->functions.rend(), [&](const auto& item) {return are_equals(item, function);});
367 if (iterator != data_->functions.rend()) data_->functions.erase((iterator + 1).base());
368 return *this;
369 }
371
372 private:
373 [[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(*)()>());}
374 [[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 {
375 auto iterator = std::find_if(begin, end, [&](const auto& item) {return are_equals(item, function);});
376 if (iterator != end) return iterator;
377 return end;
378 }
379
381 };
382
397 template<class result_t, typename ...arguments_t>
398 class delegate<result_t(arguments_t...)> : public object, public xtd::iequatable<delegate<result_t(arguments_t...)>> {
399 struct data {
400 std::vector<std::function<result_t()>> no_arguments_functions;
401 std::vector<std::function<result_t(arguments_t...)>> functions;
402 };
403
404 class async_result_invoke : public xtd::iasync_result {
405 struct data;
406 public:
407 async_result_invoke(xtd::async_callback async_callback, const xtd::any_object& async_state);
408 [[nodiscard]] auto async_state() const noexcept -> xtd::any_object override;
409 [[nodiscard]] auto async_wait_handle() noexcept -> xtd::threading::wait_handle& override;
410 [[nodiscard]] auto completed_synchronously() const noexcept -> bool override;
411 [[nodiscard]] auto is_completed() const noexcept -> bool override;
412
413 xtd::sptr<data> data_;
414 };
415
416 public:
418
421 using no_arguments_function_t = std::function<result_t()>;
423 using function_t = std::function<result_t(arguments_t...)>;
425 using no_arguments_function_collection = std::vector<no_arguments_function_t>;
427 using function_collection = std::vector<function_t>;
429
431
434 delegate() = default;
436 delegate(delegate&&) = default;
437 delegate(const delegate& other) {*data_ = *other.data_;}
438 delegate& operator =(const delegate& other) {*data_ = *other.data_; return *this;}
440
443 delegate(const function_t& function) noexcept {data_->functions.push_back(function);} // Can't be explicit by design.
444
448 template<class object1_t, typename object2_t>
449 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))));}
450
454 template<class object1_t, typename object2_t>
455 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))));}
457
459 template<class object1_t, typename object2_t, typename... args_t>
460 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))));}
461
462 template<class object1_t, typename object2_t, typename... args_t>
463 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))));}
464
465 template <typename fct_t>
466 requires (!xtd::expressions::expression_operand<fct_t>) &&
467 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
468 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
469 std::invocable<fct_t&, arguments_t...>
470 delegate(fct_t&& f) {data_->functions.push_back(function_t(std::forward<fct_t>(f)));}
471
472 template <typename fct_t>
473 requires (!xtd::expressions::expression_operand<fct_t>) &&
474 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
475 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
476 std::invocable<fct_t&>
477 delegate(fct_t&& f) {data_->no_arguments_functions.push_back(no_arguments_function_t(std::forward<fct_t>(f)));}
478
479 template <typename expression_t>
480 requires xtd::expressions::expression_operand<expression_t> &&
481 requires (expression_t e, arguments_t... args) { { e(args...) } -> std::convertible_to<result_t>;}
482 delegate(expression_t&& expression) {data_->functions.push_back(function_t(std::forward<expression_t>(expression)));}
484
486
490 [[nodiscard]] auto count() const noexcept -> xtd::usize {return data_->functions.size() + data_->no_arguments_functions.size();}
491
494 [[nodiscard]] auto no_arguments_functions() const -> const no_arguments_function_collection& {return data_->no_arguments_functions;}
495
498 [[nodiscard]] auto functions() const -> const function_collection& {return data_->functions;}
499
502 [[nodiscard]] auto is_empty() const noexcept -> bool {return count() == 0;}
503
506 [[nodiscard]] auto size() const noexcept -> xtd::usize {return count();}
508
510
520 [[nodiscard]] auto begin_invoke(arguments_t&&... arguments) -> async_result;
528 [[nodiscard]] auto begin_invoke(xtd::async_callback async_callback, arguments_t&&... arguments) -> async_result;
535 [[nodiscard]] auto begin_invoke(xtd::async_callback async_callback, const xtd::any_object& async_state, arguments_t&&... arguments) -> async_result;
536
542 auto end_invoke(async_result async) -> result_t;
543
550 auto invoke(arguments_t&&... arguments) const -> result_t {return operator()(arguments...);}
551
555 [[nodiscard]] auto equals(const object& obj) const noexcept -> bool override {return is<delegate>(obj) && equals(static_cast<const delegate&>(obj));}
559 [[nodiscard]] auto equals(const delegate& other) const noexcept -> bool override {
560 if (data_->functions.size() != other.data_->functions.size() || data_->no_arguments_functions.size() != other.data_->no_arguments_functions.size()) return false;
561 for (auto i = xtd::usize {0}; i < data_->no_arguments_functions.size(); i++)
562 if (!are_equals(data_->no_arguments_functions[i], other.data_->no_arguments_functions[i])) return false;
563 for (auto i = xtd::usize {0}; i < data_->functions.size(); i++)
564 if (!are_equals(data_->functions[i], other.data_->functions[i])) return false;
565 return true;
566 }
567
568
570
577 [[nodiscard]] static auto combine(const xtd::array<delegate>& delegates) noexcept -> delegate {
578 auto result = delegate {};
579 for (const auto& delegate : delegates) {
580 for (const auto& function : delegate.data_->no_arguments_functions)
581 result.data_->no_arguments_functions.push_back(function);
582 for (const auto& function : delegate.data_->functions)
583 result.data_->functions.push_back(function);
584 }
585 return result;
586 }
587
593 [[nodiscard]] static auto combine(const delegate& a, const delegate& b) noexcept -> delegate {
594 auto result = a;
595 for (const auto& function : b.data_->no_arguments_functions)
596 result.data_->no_arguments_functions.push_back(function);
597 for (const auto& function : b.data_->functions)
598 result.data_->functions.push_back(function);
599 return result;
600 }
601
607 [[nodiscard]] static auto combine(delegate&& a, delegate&& b) noexcept -> delegate {
608 auto result = std::move(a);
609 for (auto&& function : b.data_->no_arguments_functions)
610 result.data_->no_arguments_functions.push_back(std::move(function));
611 for (auto&& function : b.data_->functions)
612 result.data_->functions.push_back(std::move(function));
613 return result;
614 }
615
621 [[nodiscard]] static auto combine(const delegate& a, delegate&& b) noexcept -> delegate {
622 auto result = a;
623 for (auto&& function : b.data_->no_arguments_functions)
624 result.data_->no_arguments_functions.push_back(std::move(function));
625 for (auto&& function : b.data_->functions)
626 result.data_->functions.push_back(std::move(function));
627 return result;
628 }
629
635 [[nodiscard]] static auto remove(const delegate& source, const delegate& value) noexcept -> delegate {
636 auto result = source;
637 std::for_each(value.data_->no_arguments_functions.begin(), value.data_->no_arguments_functions.end(), [&](const auto& no_arguments_function) {
638 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);});
639 if (iterator != result.data_->no_arguments_functions.rend()) result.data_->no_arguments_functions.erase((iterator + 1).base());
640 });
641
642 std::for_each(value.data_->functions.begin(), value.data_->functions.end(), [&](const auto& function) {
643 auto iterator = std::find_if(result.data_->functions.rbegin(), result.data_->functions.rend(), [&](const auto& item) {return are_equals(item, function);});
644 if (iterator != result.data_->functions.rend()) result.data_->functions.erase((iterator + 1).base());
645 });
646 return result;
647 }
648
654 [[nodiscard]] static auto remove_all(const delegate& source, const delegate& value) noexcept -> delegate {
655 auto result = source;
656 for (auto function : value.data_->no_arguments_functions) {
657 if (find(result.data_->no_arguments_functions.begin(), result.data_->no_arguments_functions.end(), function) != result.data_->no_arguments_functions.end()) {
658 for (typename function_collection::reverse_iterator iterator = result.data_->no_arguments_functions.rbegin(); iterator != result.data_->no_arguments_functions.rend(); ++iterator) {
659 if (are_equals(*iterator, function))
660 result.data_->no_arguments_functions.erase((iterator + 1).base());
661 }
662 }
663 }
664
665 for (auto function : value.data_->functions) {
666 if (find(result.data_->functions.begin(), result.data_->functions.end(), function) != result.data_->functions.end()) {
667 for (auto iterator = result.data_->functions.rbegin(); iterator != result.data_->functions.rend(); ++iterator) {
668 if (are_equals(*iterator, function))
669 result.data_->functions.erase((iterator + 1).base());
670 }
671 }
672 }
673 return result;
674 }
675
676
678
683 auto operator()(arguments_t... arguments) const -> result_t {
684 if (data_->no_arguments_functions.size() == 0 && data_->functions.size() == 0) {
685 if constexpr(std::is_void_v<result_t>) return;
686 else if constexpr(std::is_reference_v<result_t>) {
687 using underlying_t = std::remove_reference_t<result_t>;
688 if constexpr(std::is_const_v<underlying_t>) {
689 static const underlying_t empty_value{};
690 return empty_value;
691 } else {
692 static underlying_t empty_value{};
693 return empty_value;
694 }
695 } else return result_t{};
696 }
697
698 if (data_->no_arguments_functions.size()) {
699 for (auto i = xtd::usize {0}; i < data_->no_arguments_functions.size() - (data_->functions.size() == 0 ? 1 : 0); i++) {
700 if (data_->no_arguments_functions[i] == nullptr) xtd::helpers::throw_helper::throws(xtd::helpers::exception_case::argument_null);
701 data_->no_arguments_functions[i]();
702 }
703
704 if (data_->functions.size() == 0) {
705 if (data_->no_arguments_functions.back() == nullptr) xtd::helpers::throw_helper::throws(xtd::helpers::exception_case::argument_null);
706 return data_->no_arguments_functions.back()();
707 }
708 }
709
710 for (auto i = xtd::usize {0}; i < data_->functions.size() - 1; i++) {
712 data_->functions[i](arguments...);
713 }
715 return data_->functions.back()(arguments...);
716 }
717
718
720 template <typename fct_t>
722 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
723 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
724 std::invocable<fct_t&, arguments_t...>
725 auto operator =(fct_t&& function) noexcept -> delegate& {
726 data_->no_arguments_functions.clear();
727 data_->functions.clear();
728 data_->functions.push_back(function_t(function));
729 return *this;
730 }
731
732 template <typename fct_t>
734 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
735 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
736 std::invocable<fct_t&>
737 auto operator =(fct_t&& function) noexcept -> delegate& {
738 data_->no_arguments_functions.clear();
739 data_->functions.clear();
740 data_->no_arguments_functions.push_back(no_arguments_function_t(function));
741 return *this;
742 }
743
744 template <typename expression_t>
746 requires (expression_t e, arguments_t... args) { { e(args...) } -> std::convertible_to<result_t>;}
747 auto operator =(expression_t&& expression) noexcept -> delegate& {
748 data_->no_arguments_functions.clear();
749 data_->functions.clear();
750 data_->functions.push_back(function_t(expression));
751 return *this;
752 }
753
754 auto operator =(const function_t& function) noexcept -> delegate& {
755 data_->no_arguments_functions.clear();
756 data_->functions.clear();
757 data_->functions.push_back(function);
758 return *this;
759 }
760
761 [[nodiscard]] auto operator +(const delegate& other) const noexcept -> delegate {
762 delegate result = *this;
763 result += other;
764 return result;
765 }
766
767 [[nodiscard]] auto operator +(const function_t& function) const noexcept -> delegate {
768 delegate result = *this;
769 result += function;
770 return result;
771 }
772
773 template <typename fct_t>
775 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
776 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
777 std::invocable<fct_t&, arguments_t...>
778 [[nodiscard]] auto operator +(fct_t&& function) noexcept -> delegate {
779 delegate result = *this;
780 result += function;
781 return result;
782 }
783
784 template <typename fct_t>
786 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
787 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
788 std::invocable<fct_t&>
789 [[nodiscard]] auto operator +(fct_t&& function) noexcept -> delegate {
790 delegate result = *this;
791 result += function;
792 return result;
793 }
794
795 template <typename expression_t>
797 requires (expression_t e, arguments_t... args) { { e(args...) } -> std::convertible_to<result_t>;}
798 [[nodiscard]] auto operator +(expression_t&& expression) noexcept -> delegate {
799 delegate result = *this;
800 result += expression;
801 return result;
802 }
803
804 auto operator +=(const delegate& other) noexcept -> delegate& {
805 for (const auto& function : other.data_->no_arguments_functions)
806 data_->no_arguments_functions.push_back(function);
807 for (const auto& function : other.data_->functions)
808 data_->functions.push_back(function);
809 return *this;
810 }
811
812 auto operator +=(delegate&& other) noexcept -> delegate& {
813 for (auto&& function : other.data_->no_arguments_functions)
814 data_->no_arguments_functions.push_back(std::move(function));
815 for (auto&& function : other.data_->functions)
816 data_->functions.push_back(std::move(function));
817 return *this;
818 }
819
820 auto operator +=(const function_t& function) noexcept -> delegate& {
821 data_->functions.push_back(function);
822 return *this;
823 }
824
825 template <typename fct_t>
827 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
828 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
829 std::invocable<fct_t&, arguments_t...>
830 auto operator +=(fct_t&& function) noexcept -> delegate& {
831 *this += delegate(function);
832 return *this;
833 }
834
835 template <typename fct_t>
837 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
838 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
839 std::invocable<fct_t&>
840 auto operator +=(fct_t&& function) noexcept -> delegate& {
841 *this += delegate(function);
842 return *this;
843 }
844
845 template <typename expression_t>
847 requires (expression_t e, arguments_t... args) { { e(args...) } -> std::convertible_to<result_t>;}
848 auto operator +=(expression_t&& expression) noexcept -> delegate& {
849 *this += delegate(expression);
850 return *this;
851 }
852
853 [[nodiscard]] auto operator -(const delegate& other) const noexcept -> delegate {
854 delegate result = *this;
855 result -= other;
856 return result;
857 }
858
859 [[nodiscard]] auto operator -(const function_t& function) const noexcept -> delegate {
860 delegate result = *this;
861 result -= function;
862 return result;
863 }
864
865 template <typename fct_t>
867 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
868 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
869 std::invocable<fct_t&, arguments_t...>
870 [[nodiscard]] auto operator -(fct_t&& function) noexcept -> delegate {
871 delegate result = *this;
872 result -= function;
873 return result;
874 }
875
876 template <typename fct_t>
878 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
879 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
880 std::invocable<fct_t&>
881 [[nodiscard]] auto operator -(fct_t&& function) noexcept -> delegate {
882 delegate result = *this;
883 result -= function;
884 return result;
885 }
886
887 template <typename expression_t>
889 requires (expression_t e, arguments_t... args) { { e(args...) } -> std::convertible_to<result_t>;}
890 [[nodiscard]] auto operator -(expression_t&& expression) noexcept -> delegate {
891 delegate result = *this;
892 result -= expression;
893 return result;
894 }
895
896 auto operator -=(const delegate& other) noexcept -> delegate& {
897 std::for_each(other.data_->no_arguments_functions.begin(), other.data_->no_arguments_functions.end(), [&](const auto& no_arguments_function) {
898 auto iterator = std::find_if(data_->no_arguments_functions.rbegin(), data_->no_arguments_functions.rend(), [&](const auto& item) {return are_equals(item, no_arguments_function);});
899 if (iterator != data_->no_arguments_functions.rend()) data_->no_arguments_functions.erase((iterator + 1).base());
900 });
901
902 std::for_each(other.data_->functions.begin(), other.data_->functions.end(), [&](const auto& function) {
903 auto iterator = std::find_if(data_->functions.rbegin(), data_->functions.rend(), [&](const auto& item) {return are_equals(item, function);});
904 if (iterator != data_->functions.rend()) data_->functions.erase((iterator + 1).base());
905 });
906 return *this;
907 }
908
909 auto operator -=(const function_t& function) noexcept -> delegate& {
910 auto iterator = std::find_if(data_->functions.rbegin(), data_->functions.rend(), [&](const auto& item) {return are_equals(item, function);});
911 if (iterator != data_->functions.rend()) data_->functions.erase((iterator + 1).base());
912 return *this;
913 }
914
915 auto operator -=(const no_arguments_function_t& no_arguments_function) noexcept -> delegate& {
916 auto iterator = std::find_if(data_->no_arguments_functions.rbegin(), data_->no_arguments_functions.rend(), [&](const auto& item) {return are_equals(item, no_arguments_function);});
917 if (iterator != data_->no_arguments_functions.rend()) data_->no_arguments_functions.erase((iterator + 1).base());
918 return *this;
919 }
920
921 template <typename fct_t>
923 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
924 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
925 std::invocable<fct_t&, arguments_t...>
926 auto operator -=(fct_t&& function) noexcept -> delegate& {
927 auto iterator = std::find_if(data_->functions.rbegin(), data_->functions.rend(), [&](const auto& item) {return are_equals(item, function);});
928 if (iterator != data_->functions.rend()) data_->functions.erase((iterator + 1).base());
929 return *this;
930 }
931
932 template <typename fct_t>
934 (!std::same_as<std::decay_t<fct_t>, delegate>) &&
935 (!std::same_as<std::decay_t<fct_t>, function_t>) &&
936 std::invocable<fct_t&>
937 auto operator -=(fct_t&& function) noexcept -> delegate& {
938 auto iterator = std::find_if(data_->functions.rbegin(), data_->functions.rend(), [&](const auto& item) {return are_equals(item, function);});
939 if (iterator != data_->functions.rend()) data_->functions.erase((iterator + 1).base());
940 return *this;
941 }
942
943 template <typename expression_t>
945 requires (expression_t e, arguments_t... args) { { e(args...) } -> std::convertible_to<result_t>;}
946 auto operator -=(expression_t&& expression) noexcept -> delegate& {
947 auto iterator = std::find_if(data_->functions.rbegin(), data_->functions.rend(), [&](const auto& item) {return are_equals(item, function_t {expression});});
948 if (iterator != data_->functions.rend()) data_->functions.erase((iterator + 1).base());
949 return *this;
950 }
952
953 private:
954 struct delegate_async_state;
955
956 [[nodiscard]] static auto are_equals(const std::function<result_t(arguments_t...)>& fct1, const std::function<result_t(arguments_t...)>& fct2) noexcept -> bool {
957 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...)>());
958 }
959
960 [[nodiscard]] static auto are_equals(const std::function<result_t()>& fct1, const std::function<result_t()>& fct2) noexcept -> bool {
961 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(*)()>());
962 }
963
964 [[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 {
965 auto iterator = std::find_if(begin, end, [&](const auto& item) {return are_equals(item, function);});
966 if (iterator != end) return iterator;
967 return end;
968 }
969
970 [[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 {
971 auto iterator = std::find_if(begin, end, [&](const auto& item) {return are_equals(item, function);});
972 if (iterator != end) return iterator;
973 return end;
974 }
975
977 };
978
980 // Deduction guides for xtd::delegate
981 // {
982 template<typename>
983 struct function_traits;
984
985 template<typename result_t, typename... args_t>
986 struct function_traits<result_t(args_t...)> {using signature = result_t(args_t...);};
987
988 template<typename result_t, typename... args_t>
989 struct function_traits<result_t(*)(args_t...)> : function_traits<result_t(args_t...)> {};
990
991 template<typename class_t, typename result_t, typename... args_t>
992 struct function_traits<result_t(class_t::*)(args_t...) const> : function_traits<result_t(args_t...)> {};
993
994 template<typename type_t>
995 struct function_traits : function_traits<decltype(&type_t::operator())> {};
996
997 template<typename function_t>
998 delegate(function_t) -> delegate<typename function_traits<function_t>::signature>;
999
1000 template<typename result_t, typename... args_t>
1001 delegate(std::function<result_t(args_t...)>) -> delegate<result_t(args_t...)>;
1002 // }
1004}
1005
1018#define delegate_ \
1019 [&]
1020
1021// 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:506
std::vector< function_t > function_collection
function_t Represents the function collection type.
Definition delegate.hpp:427
static auto combine(const delegate &a, delegate &&b) noexcept -> delegate
Concatenates the invocation lists of two delegates.
Definition delegate.hpp:621
auto is_empty() const noexcept -> bool
Return if the delegate is empty.
Definition delegate.hpp:502
auto no_arguments_functions() const -> const no_arguments_function_collection &
Gets the no arguments delegates array.
Definition delegate.hpp:494
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:654
auto functions() const -> const function_collection &
Gets the delegates array.
Definition delegate.hpp:498
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:455
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:559
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:635
static auto combine(delegate &&a, delegate &&b) noexcept -> delegate
Concatenates the invocation lists of two delegates.
Definition delegate.hpp:607
static auto combine(const delegate &a, const delegate &b) noexcept -> delegate
Concatenates the invocation lists of two delegates.
Definition delegate.hpp:593
auto operator()(arguments_t... arguments) const -> result_t
invokes the method represented by the current delegate.
Definition delegate.hpp:683
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:555
std::vector< no_arguments_function_t > no_arguments_function_collection
function_t Represents the no arguments function collection type.
Definition delegate.hpp:425
std::function< result_t(arguments_t...)> function_t
Represents function type.
Definition delegate.hpp:423
static auto combine(const xtd::array< delegate > &delegates) noexcept -> delegate
Concatenates the invocation lists of an array of delegates.
Definition delegate.hpp:577
auto count() const noexcept -> xtd::usize
Return the size of invocation list.
Definition delegate.hpp:490
delegate(const function_t &function) noexcept
Initializes a delegate that invokes the specified instance method.
Definition delegate.hpp:443
auto invoke(arguments_t &&... arguments) const -> result_t
invokes the method represented by the current delegate.
Definition delegate.hpp:550
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:421
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:449
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 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.