Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <tuple>
- #include <vector>
- #include <type_traits>
- #include <chrono>
- // ---------------------------------------------------------
- // tuple_vector, can be used as heterogenous container
- // ---------------------------------------------------------
- template <typename... Args>
- struct tuple_vector : std::tuple< std::vector<Args>... >
- {
- typename std::tuple<Args...> type;
- template <typename T>
- void push_back(const T& value)
- { std::get< std::vector<T> >(*this).push_back(value); }
- template <typename T>
- void push_back( T&& value)
- { std::get< std::vector<T> >(*this).push_back(value); }
- };
- // ---------------------------------------------------------
- // invoke type trait helpers
- // ---------------------------------------------------------
- template <typename T, typename _ = void>
- struct is_vector : std::false_type { };
- template <typename T>
- using same_as_vector = typename std::enable_if_t
- < std::is_same<T, std::vector<typename T::value_type,typename T::allocator_type> >{}() >;
- template <typename T>
- struct is_vector<T, same_as_vector<T>> : std::true_type { };
- template <typename... T> struct is_tuple_vector : std::false_type { };
- template <typename... T> struct is_tuple_vector< tuple_vector<T...> > : std::true_type { };
- // ---------------------------------------------------------
- // invoke#1: matches anything except vectors and tuple_vectors
- // ---------------------------------------------------------
- template <typename F, typename T, typename... Args,
- typename std::enable_if<!is_vector<T>::value && !is_tuple_vector<T>::value>::type* = nullptr>
- inline void invoke(T& e, Args... args)
- {
- F::invoke(e, std::forward<Args>(args)...);
- }
- // ---------------------------------------------------------
- // invoke#2: matches vectors
- // ---------------------------------------------------------
- template <typename F, typename T, typename... Args>
- inline void invoke(std::vector<T>& ve, Args... args)
- {
- for (auto &e: ve) F::invoke(e, std::forward<Args>(args)...);
- }
- // ---------------------------------------------------------
- // invoke_tuple_impl: invoke the elements in the Ith tuple element
- // ---------------------------------------------------------
- template <std::size_t I, typename F, typename... T, typename... Args,
- typename std::enable_if<(I < sizeof...(T))>::type* = nullptr>
- inline void invoke_tuple_impl(std::tuple<T...>& te, Args... args)
- {
- //std::cout << "processing tuple element " << I << "\n";
- for (auto &e: std::get<I>(te))
- F::invoke(e, std::forward<Args>(args)...);
- invoke_tuple_impl<I+1,F>(te, std::forward<Args>(args)...);
- }
- // ---------------------------------------------------------
- // invoke_tuple_impl: tail case
- // ---------------------------------------------------------
- template <std::size_t I, typename F, typename... T, typename... Args,
- typename std::enable_if<(I == sizeof...(T))>::type* = nullptr>
- inline void invoke_tuple_impl(std::tuple<T...>& te, Args... args)
- {}
- // ---------------------------------------------------------
- // invoke#2: matches tuple_vectors
- // ---------------------------------------------------------
- template <typename F, typename... T, typename... Args>
- inline void invoke(std::tuple<T...>& te, Args... args)
- {
- invoke_tuple_impl<0,F>(te,std::forward<Args>(args)...);
- }
- // ---------------------------------------------------------
- // Base Shapes
- // ---------------------------------------------------------
- struct Point {
- double x;
- double y;
- constexpr static auto name = "Point";
- };
- struct Line {
- double x;
- double y;
- double a;
- double l;
- constexpr static auto name = "Line";
- };
- struct Rectangle {
- double x;
- double y;
- double a;
- double w;
- double h;
- constexpr static auto name = "Rectangle";
- };
- struct Circle {
- double x;
- double y;
- double r;
- constexpr static auto name = "Circle";
- };
- // ---------------------------------------------------------
- // Operators
- // ---------------------------------------------------------
- struct Move {
- template <typename T>
- static void invoke(T& shape, double x, double y) {
- //std::cout << "moved " << T::name << " to " << x << "," << y << "\n";
- shape.x = x;
- shape.y = y;
- }
- };
- struct Shift {
- template <typename T>
- static void invoke(T& shape, double dx, double dy) {
- //std::cout << "shifting " << T::name << " with (" << dx << " , " << dy << ") pre = (" << shape.x << " , " << shape.y << ") post = (";
- shape.x += dx;
- shape.y += dy;
- //std::cout << shape.x << " , " << shape.y << ")\n";
- }
- };
- struct Rotate {
- template <typename T>
- static void invoke(T& shape, double angle) {
- //std::cout << "rotated " << T::name << " with " << angle << "deg\n";
- shape.a += angle;
- }
- };
- struct Print {
- template <typename T>
- static void invoke(T& shape) {
- std::cout << T::name << ": {" << shape.x << "," << shape.y << "}\n";
- }
- };
- // ---------------------------------------------------------
- // Specialisations
- // ---------------------------------------------------------
- template<> void Rotate::invoke(Point&, double) {
- //std::cout << "skipped rotating a point\n";
- };
- template<> void Rotate::invoke(Circle&, double) {
- //std::cout << "skipped rotating a circle\n";
- };
- int main()
- {
- typedef std::chrono::high_resolution_clock Clock;
- // Store 4.000.000 shapes
- tuple_vector<Point, Line, Rectangle, Circle> shapes;
- auto t1 = Clock::now();
- for (double x=1; x<1000.5; x+=1.0) {
- for (double y=1; y<1000.5; y+=1.0) {
- shapes.push_back( Point{x,y} );
- shapes.push_back( Line{x,y,0,1} );
- shapes.push_back( Rectangle{x,y,0,1,1} );
- shapes.push_back( Circle{x,y,1} );
- }
- }
- auto t2 = Clock::now();
- std::cout << "push_back: " << std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count()<< " us\n";
- {
- auto ts = Clock::now();
- for (auto r=0; r<10; ++r)
- invoke<Shift>(shapes, .928347923874, .1908347438);
- auto te = Clock::now();
- std::cout << "Shift: " << std::chrono::duration_cast<std::chrono::microseconds>(te - ts).count() << " us\n";
- }
- {
- auto ts = Clock::now();
- for (auto r=0; r<10; ++r)
- invoke<Rotate>(shapes, 180);
- auto te = Clock::now();
- std::cout << "Rotate: " << std::chrono::duration_cast<std::chrono::microseconds>(te - ts).count() << " us\n";
- }
- {
- auto ts = Clock::now();
- for (auto r=0; r<10; ++r)
- invoke<Move>(shapes, .2, .5);
- auto te = Clock::now();
- std::cout << "Move: " << std::chrono::duration_cast<std::chrono::microseconds>(te - ts).count() << " us\n";
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement