Advertisement
Guest User

Untitled

a guest
Aug 24th, 2014
319
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.90 KB | None | 0 0
  1. #include <iostream>
  2. #include <tuple>
  3. #include <vector>
  4. #include <type_traits>
  5. #include <chrono>
  6.  
  7. // ---------------------------------------------------------
  8. // tuple_vector, can be used as heterogenous container
  9. // ---------------------------------------------------------
  10. template <typename... Args>
  11. struct tuple_vector :  std::tuple< std::vector<Args>... >
  12. {
  13.     typename std::tuple<Args...> type;
  14.    
  15.     template <typename T>
  16.     void push_back(const T& value)
  17.     { std::get< std::vector<T> >(*this).push_back(value); }
  18.    
  19.     template <typename T>
  20.     void push_back(     T&& value)
  21.     { std::get< std::vector<T> >(*this).push_back(value); }
  22. };
  23.  
  24. // ---------------------------------------------------------
  25. // invoke type trait helpers
  26. // ---------------------------------------------------------
  27. template <typename T, typename _ = void>
  28. struct is_vector : std::false_type { };
  29.  
  30. template <typename T>
  31. using same_as_vector = typename std::enable_if_t
  32. < std::is_same<T, std::vector<typename T::value_type,typename T::allocator_type> >{}() >;
  33.  
  34. template <typename T>
  35. struct is_vector<T, same_as_vector<T>> : std::true_type { };
  36.  
  37. template <typename... T> struct is_tuple_vector : std::false_type { };
  38. template <typename... T> struct is_tuple_vector< tuple_vector<T...> > : std::true_type { };
  39.  
  40. // ---------------------------------------------------------
  41. // invoke#1: matches anything except vectors and tuple_vectors
  42. // ---------------------------------------------------------
  43. template <typename F, typename T, typename... Args,
  44.         typename std::enable_if<!is_vector<T>::value && !is_tuple_vector<T>::value>::type* = nullptr>
  45. inline void invoke(T& e, Args... args)
  46. {
  47.     F::invoke(e, std::forward<Args>(args)...);
  48. }
  49.  
  50. // ---------------------------------------------------------
  51. // invoke#2: matches vectors
  52. // ---------------------------------------------------------
  53. template <typename F, typename T, typename... Args>
  54. inline void invoke(std::vector<T>& ve, Args... args)
  55. {
  56.     for (auto &e: ve) F::invoke(e, std::forward<Args>(args)...);
  57. }
  58.  
  59. // ---------------------------------------------------------
  60. // invoke_tuple_impl: invoke the elements in the Ith tuple element
  61. // ---------------------------------------------------------
  62. template <std::size_t I, typename F, typename... T, typename... Args,
  63.     typename std::enable_if<(I < sizeof...(T))>::type* = nullptr>
  64. inline void invoke_tuple_impl(std::tuple<T...>& te, Args... args)
  65. {
  66.     //std::cout << "processing tuple element " << I << "\n";
  67.     for (auto &e: std::get<I>(te))
  68.         F::invoke(e, std::forward<Args>(args)...);
  69.     invoke_tuple_impl<I+1,F>(te, std::forward<Args>(args)...);
  70. }
  71.  
  72. // ---------------------------------------------------------
  73. // invoke_tuple_impl: tail case
  74. // ---------------------------------------------------------
  75. template <std::size_t I, typename F, typename... T, typename... Args,
  76.     typename std::enable_if<(I == sizeof...(T))>::type* = nullptr>
  77. inline void invoke_tuple_impl(std::tuple<T...>& te, Args... args)
  78. {}
  79.  
  80. // ---------------------------------------------------------
  81. // invoke#2: matches tuple_vectors
  82. // ---------------------------------------------------------
  83. template <typename F, typename... T, typename... Args>
  84. inline void invoke(std::tuple<T...>& te, Args... args)
  85. {
  86.     invoke_tuple_impl<0,F>(te,std::forward<Args>(args)...);
  87. }
  88.  
  89.  
  90. // ---------------------------------------------------------
  91. // Base Shapes
  92. // ---------------------------------------------------------
  93. struct Point {
  94.     double x;
  95.     double y;
  96.     constexpr static auto name = "Point";
  97. };
  98.  
  99. struct Line {
  100.     double x;
  101.     double y;
  102.     double a;
  103.     double l;
  104.     constexpr static auto name = "Line";
  105. };
  106.  
  107. struct Rectangle {
  108.     double x;
  109.     double y;
  110.     double a;
  111.     double w;
  112.     double h;
  113.     constexpr static auto name = "Rectangle";
  114. };
  115.  
  116. struct Circle {
  117.     double x;
  118.     double y;
  119.     double r;
  120.     constexpr static auto name = "Circle";
  121. };
  122.  
  123.  
  124. // ---------------------------------------------------------
  125. // Operators
  126. // ---------------------------------------------------------
  127. struct Move {
  128.     template <typename T>
  129.     static void invoke(T& shape, double x, double y) {
  130.         //std::cout << "moved " << T::name << " to " << x << "," << y << "\n";
  131.         shape.x = x;
  132.         shape.y = y;
  133.     }
  134. };
  135.  
  136. struct Shift {
  137.     template <typename T>
  138.     static void invoke(T& shape, double dx, double dy) {
  139.         //std::cout << "shifting " << T::name << " with (" << dx << " , " << dy << ") pre = (" << shape.x << " , " << shape.y << ") post = (";
  140.         shape.x += dx;
  141.         shape.y += dy;
  142.         //std::cout << shape.x << " , " << shape.y << ")\n";
  143.     }
  144. };
  145.  
  146. struct Rotate {
  147.     template <typename T>
  148.     static void invoke(T& shape, double angle) {
  149.         //std::cout << "rotated " << T::name << " with " << angle << "deg\n";
  150.         shape.a += angle;
  151.     }
  152. };
  153.  
  154. struct Print {
  155.     template <typename T>
  156.     static void invoke(T& shape) {
  157.         std::cout << T::name << ": {" << shape.x << "," << shape.y << "}\n";
  158.     }
  159. };
  160.  
  161. // ---------------------------------------------------------
  162. // Specialisations
  163. // ---------------------------------------------------------
  164. template<> void Rotate::invoke(Point&, double) {
  165.     //std::cout << "skipped rotating a point\n";
  166. };
  167.  
  168. template<> void Rotate::invoke(Circle&, double) {
  169.     //std::cout << "skipped rotating a circle\n";
  170. };
  171.  
  172.  
  173. int main()
  174. {
  175.     typedef std::chrono::high_resolution_clock Clock;
  176.  
  177.     // Store 4.000.000 shapes
  178.     tuple_vector<Point, Line, Rectangle, Circle> shapes;
  179.     auto t1 = Clock::now();
  180.     for (double x=1; x<1000.5; x+=1.0) {
  181.         for (double y=1; y<1000.5; y+=1.0) {
  182.             shapes.push_back( Point{x,y} );
  183.             shapes.push_back( Line{x,y,0,1} );
  184.             shapes.push_back( Rectangle{x,y,0,1,1} );
  185.             shapes.push_back( Circle{x,y,1} );
  186.         }
  187.     }
  188.     auto t2 = Clock::now();
  189.     std::cout << "push_back: " << std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count()<< " us\n";
  190.  
  191.     {
  192.         auto ts = Clock::now();
  193.         for (auto r=0; r<10; ++r)
  194.             invoke<Shift>(shapes, .928347923874, .1908347438);
  195.         auto te = Clock::now();
  196.         std::cout << "Shift: " << std::chrono::duration_cast<std::chrono::microseconds>(te - ts).count() << " us\n";
  197.     }
  198.    
  199.     {
  200.         auto ts = Clock::now();
  201.         for (auto r=0; r<10; ++r)
  202.             invoke<Rotate>(shapes, 180);
  203.         auto te = Clock::now();
  204.         std::cout << "Rotate: " << std::chrono::duration_cast<std::chrono::microseconds>(te - ts).count() << " us\n";
  205.     }
  206.  
  207.     {
  208.         auto ts = Clock::now();
  209.         for (auto r=0; r<10; ++r)
  210.             invoke<Move>(shapes, .2, .5);
  211.         auto te = Clock::now();
  212.         std::cout << "Move: " << std::chrono::duration_cast<std::chrono::microseconds>(te - ts).count() << " us\n";
  213.     }
  214.  
  215. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement