akela43

multimethod2

Feb 1st, 2019
242
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.27 KB | None | 0 0
  1. #include <iostream>
  2. #include <typeinfo>
  3. #include <typeindex>
  4. #include <unordered_map>
  5. #include <utility>
  6. #include <functional>
  7. struct pair_hash {
  8.     template <class T1, class T2>
  9.     std::size_t operator () (const std::pair<T1,T2> &p) const {
  10.         auto h1 = std::hash<T1>{}(p.first);
  11.         auto h2 = std::hash<T2>{}(p.second);
  12.         return h1 ^ h2; //XOR
  13.     }
  14. };
  15. template <class T, class R, bool Commutative>
  16. class Multimethod2
  17. {
  18. public:
  19.     using Index = std::pair< std::type_index,  std::type_index>;
  20.     using  F = std::function<R(T *, T *)>;
  21.     using Unordered_map = std::unordered_map<Index, F, pair_hash>;
  22.  
  23.     Unordered_map mF;
  24.     Multimethod2() {}
  25.  
  26.     void addImpl( const std::type_info  &l,  const std::type_info &r, F f) {
  27.  
  28.         mF[std::make_pair(std::type_index(l),std::type_index(r))] = f;
  29. //        if (l != r)
  30. //            if (Commutative) mF[std::make_pair(std::type_index(r),std::type_index(l))] = f;
  31.  
  32.     }
  33.     bool hasImpl(T* l, T* r) const {
  34.  
  35.         if ( mF.find({std::type_index(typeid(*l)), std::type_index(typeid(*r))}) != mF.end() )
  36.             return true;
  37.         if (Commutative)
  38.             if ( mF.find({std::type_index(typeid(*r)), std::type_index(typeid(*l))}) != mF.end() )
  39.                 return true;
  40.         return false;
  41.     }
  42.  
  43.     R call(T* l, T* r) const {
  44.         auto it = mF.find({std::type_index(typeid(*l)), std::type_index(typeid(*r))});
  45.         if (it !=mF.end())  {
  46.             return (it->second)(l,r);
  47.         }
  48.         if (Commutative) {
  49.             it = mF.find({std::type_index(typeid(*l)), std::type_index(typeid(*r))});
  50.             if (it !=mF.end())  {
  51.                 return (it->second)(l,r);
  52.             }
  53.         }
  54.         return R();
  55.  
  56.     }
  57.  
  58. };
  59.  
  60. ///////////////
  61. #include <iostream>
  62. #include <typeinfo>
  63. #include <typeindex>
  64. #include <unordered_map>
  65. #include <multimetod.h>
  66. #include <string>
  67.  
  68.  
  69. using namespace std;
  70. // базовый класс фигуры (полиморфный)
  71. struct Shape {
  72. public:
  73.     virtual ~Shape() = 0;
  74.  
  75.  
  76. };
  77. Shape::~Shape() {}
  78.  
  79. // прямоугольник
  80. struct Rectangle : Shape {
  81.     Rectangle(int x, int y, int x2, int y2) :
  82.         x(x), y(y), x2(x2), y2(y2) { }
  83.     Rectangle() : Rectangle(4,4,4,4) {}
  84.  
  85.     int x;
  86.     int y;
  87.     int x2;
  88.     int y2;
  89.     ~Rectangle() {}
  90.  
  91.  
  92. };
  93.  
  94. // треугольник
  95. struct Triangle : Shape
  96. {
  97.     Triangle(int x, int y, int x2) :
  98.         x(x), y(y), x2(x2) { }
  99.     Triangle(): Triangle(3,3,3){}
  100.  
  101.     int x;
  102.     int y;
  103.     int x2;
  104.     ~Triangle() {}
  105.  
  106. };
  107.  
  108. void f1( Triangle t) {
  109.     std::cout << __func__ << std::endl;
  110. }
  111.  
  112. void f2( Rectangle r) {
  113.     std::cout << __func__ << std::endl;
  114. }
  115.  
  116. // функция для проверки пересечения двух прямоугольников
  117. std::string is_intersect_r_r(Shape * a, Shape * b) {
  118.     std::cout << __func__;
  119.     return "is_intersect_r_r";}
  120.  
  121. // функция для проверки пересечения прямоугольника и треугольника
  122. std::string is_intersect_r_t(Shape * a, Shape * b) {
  123.     std::cout << __func__;
  124.     return "is_intersect_r_t";}
  125. void is_intersect_r_t_v(Shape * a, Shape * b) {
  126.     std::cout << __func__;
  127.     }
  128.  
  129. int main()
  130. {
  131.     Shape *t1 = new Triangle();
  132.     Shape *t2 = new Triangle();
  133.      Shape* t3 = new Rectangle();
  134.      {
  135.          Multimethod2<Shape, void, true> is_intersect;
  136.         is_intersect.addImpl(typeid(Rectangle), typeid(Rectangle), is_intersect_r_t_v);
  137.         Shape * s1 = new Rectangle();
  138.         Shape * s2 = new Triangle();
  139.         if (is_intersect.hasImpl(s1, s2))
  140.            {
  141.             std::cout << "true\n";
  142.  
  143.                 // вызывается функция is_intersect_r_t(s2, s1)
  144.                 is_intersect.call(s1, s2);
  145.  
  146.  
  147.                 // Замечание: is_intersect_r_t ожидает,
  148.                 // что первым аргументом будет прямоугольник
  149.                 // а вторым треугольник, а здесь аргументы
  150.                 // передаются в обратном порядке.
  151.                 // ваша реализация должна самостоятельно
  152.                 // об этом позаботиться
  153.            }
  154.      }
  155.     Multimethod2<Shape, std::string, true> is_intersect;
  156.    is_intersect.addImpl(typeid(Rectangle), typeid(Rectangle), is_intersect_r_r);
  157.    is_intersect.addImpl(typeid(Rectangle), typeid(Triangle), is_intersect_r_t);
  158.    Shape * s1 = new Rectangle();
  159.    Shape * s2 = new Triangle();
  160.  
  161.    if (is_intersect.hasImpl(s2, s1))
  162.       {
  163.        std::cout << true;
  164.  
  165.            // вызывается функция is_intersect_r_t(s2, s1)
  166.            auto res = is_intersect.call(s2, s1);
  167.            std::cout << res;
  168.  
  169.            // Замечание: is_intersect_r_t ожидает,
  170.            // что первым аргументом будет прямоугольник
  171.            // а вторым треугольник, а здесь аргументы
  172.            // передаются в обратном порядке.
  173.            // ваша реализация должна самостоятельно
  174.            // об этом позаботиться
  175.       }
  176.  
  177.  
  178.  
  179.     return 0;
  180. }
Advertisement
Add Comment
Please, Sign In to add comment