qxLib
double_dispatch_matrix.inl
Go to the documentation of this file.
1 /**
2 
3  @file double_dispatch_matrix.inl
4  @author Khrapov
5  @date 17.01.2025
6  @copyright © Nick Khrapov, 2025. All right reserved.
7 
8 **/
9 
10 namespace qx
11 {
12 
13 template<auto method_ptr_t>
14  requires is_specialization_exist_v<double_dispatch_class_method_ptr_traits<method_ptr_t>>
15 template<class first_derived_t, class second_derived_t>
16  requires(
17  std::is_base_of_v<typename double_dispatch_matrix<method_ptr_t>::base_type, first_derived_t>
18  && std::is_base_of_v<typename double_dispatch_matrix<method_ptr_t>::base_type, second_derived_t>)
19 void double_dispatch_matrix<method_ptr_t>::register_function(
20  std::function<return_type(const first_derived_t&, const second_derived_t&)> function) noexcept
21 {
22  get_function(first_derived_t::get_class_id_static(), second_derived_t::get_class_id_static()) = function_type(
23  [function_ = std::move(function)](const base_type& first, const base_type& second)
24  {
25  const first_derived_t* first_as_first_derived_t = rtti_cast<const first_derived_t>(first);
26  if (first_as_first_derived_t)
27  {
28  return function_(*first_as_first_derived_t, static_cast<const second_derived_t&>(second));
29  }
30 
31  return function_(static_cast<const first_derived_t&>(second), static_cast<const second_derived_t&>(first));
32  });
33 }
34 
35 template<auto method_ptr_t>
36  requires is_specialization_exist_v<double_dispatch_class_method_ptr_traits<method_ptr_t>>
37 std::optional<typename double_dispatch_matrix<method_ptr_t>::return_type> double_dispatch_matrix<method_ptr_t>::invoke(
38  const base_type& first,
39  const base_type& second)
40 {
41  if (function_type& function = get_function(first.get_class_id(), second.get_class_id()))
42  return function(first, second);
43  else
44  return std::nullopt;
45 }
46 
47 template<auto method_ptr_t>
48  requires is_specialization_exist_v<double_dispatch_class_method_ptr_traits<method_ptr_t>>
49 bool double_dispatch_matrix<method_ptr_t>::check_matrix_completeness() const noexcept
50 {
51  size_t nTotalElements = 0;
52  return std::ranges::all_of(
53  m_MatrixFunctions,
54  [&nTotalElements](const auto& pair)
55  {
56  nTotalElements += pair.second.size();
57  return std::ranges::all_of(
58  pair.second,
59  [](const auto& pair)
60  {
61  return static_cast<bool>(pair.second);
62  });
63  })
64  && nTotalElements == (m_MatrixFunctions.size() * m_MatrixFunctions.size() + m_MatrixFunctions.size()) / 2;
65 }
66 
67 template<auto method_ptr_t>
68  requires is_specialization_exist_v<double_dispatch_class_method_ptr_traits<method_ptr_t>>
69 typename double_dispatch_matrix<method_ptr_t>::function_type& double_dispatch_matrix<method_ptr_t>::get_function(
70  class_id first,
71  class_id second) noexcept
72 {
73  const class_id first_in_container = std::min(first, second);
74  const class_id second_in_container = std::max(first, second);
75  return m_MatrixFunctions[first_in_container][second_in_container];
76 }
77 
78 } // namespace qx