//******************************************************** // The following code example is taken from the book // C++17 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd17.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** #include "geoobj.hpp" #include "circle.hpp" #include "line.hpp" #include "polygon.hpp" #include #include #include #include #include #include "tracknew.hpp" #include using GOType = std::variant; using GOColl = std::vector; GOColl initColl(int num) { GOColl coll; coll.reserve(num); for (int i=1; i < num/3 + 1; ++i) { Line l{"Line" + std::to_string(i), Coord{i,i}, Coord{100*i,100*i}}; coll.push_back(l); Circle c{"Circle" + std::to_string(i), Coord{10*i,10*i}, i}; coll.push_back(c); Polygon p{"Polygon" + std::to_string(i), {Coord{i,i}, Coord{i, -i}, Coord{-i, -i}, Coord{-i, i}}}; coll.push_back(p); } return coll; } void cleanColl(GOColl& coll) { coll.clear(); } long iterate(const GOColl& coll) { long numEmpty = 0; for (const auto& go : coll) { std::visit([&numEmpty] (const auto& obj) { if (obj.getName().empty()) { ++numEmpty; } }, go); } return numEmpty; } long iterateDown(const GOColl& coll) { long sumPoints = 0; for (const auto& go : coll) { if (auto p = std::get_if(&go); p != nullptr) { sumPoints += p->numPoints(); } } return sumPoints; } class NumPoints { private: long sumPoints{0}; public: void operator() (const Polygon& p) { sumPoints += p.numPoints(); } template void operator() (const T&) { } long getSum() const { return sumPoints; } }; long iterateDown2(const GOColl& coll) { NumPoints fo; for (const auto& go : coll) { std::visit(fo, go); } return fo.getSum(); } void shuffleAndMod(GOColl& coll) { std::default_random_engine dre; std::shuffle(coll.begin(), coll.end(), // range dre); // random number generator for (auto& go : coll) { std::visit([] (auto& obj) { obj.move(Coord{0,1}); }, go); } } void sort(GOColl& coll) { /* auto getName = [] (const auto& obj) { return obj.getName(); }; std::sort(coll.begin(), coll.end(), [getName] (const auto& go1, const auto& go2) { return std::visit(getName, go1) < std::visit(getName, go2); }); */ auto getName = [](const auto& go) { return std::visit([] (const auto& obj) { return obj.getName(); }, go); }; std::sort(coll.begin(), coll.end(), [getName] (const auto& go1, const auto& go2) { return getName(go1) < getName(go2); }); } void copy(const GOColl& coll) { GOColl coll2{coll}; assert(coll.size() == coll2.size()); #ifdef PRINT std::cout << " "; std::visit([] (const auto& obj) { obj.draw(); }, coll[coll.size()-1]); #endif } void covariant(const GOColl& coll) { for (const auto& go : coll) { auto g = go; assert((std::is_same_v)); //... // e.g., std::visit(..., g); // no need to call delete } } int main(int argc, const char** argv) { int num = 10000; if (argc > 1) { num = std::atoi(argv[1]); } std::cout << "***********************************************\n"; std::map> data; const int numLoops = 10; int numMeasured = 0; for (int i=0; i(t1b-t1a); std::cout << "**** initColl(): " << d1.count() << " ms\n"; auto t2a = std::chrono::high_resolution_clock::now(); shuffleAndMod(coll); auto t2b = std::chrono::high_resolution_clock::now(); auto d2 = std::chrono::duration(t2b-t2a); std::cout << "**** shuffleAndMod(): " << d2.count() << " ms\n"; auto t3a = std::chrono::high_resolution_clock::now(); sort(coll); auto t3b = std::chrono::high_resolution_clock::now(); auto d3 = std::chrono::duration(t3b-t3a); std::cout << "**** sort(): " << d3.count() << " ms\n"; auto t4a = std::chrono::high_resolution_clock::now(); copy(coll); auto t4b = std::chrono::high_resolution_clock::now(); auto d4 = std::chrono::duration(t4b-t4a); std::cout << "**** copy() " << d4.count() << " ms\n"; auto t5a = std::chrono::high_resolution_clock::now(); auto numEmpty = iterate(coll); auto t5b = std::chrono::high_resolution_clock::now(); auto d5 = std::chrono::duration(t5b-t5a); std::cout << "**** iterate():): " << d5.count() << " ms\n"; std::cout << " " << numEmpty << " empty names\n"; auto t6a = std::chrono::high_resolution_clock::now(); auto numPoints = iterateDown(coll); auto t6b = std::chrono::high_resolution_clock::now(); auto d6 = std::chrono::duration(t6b-t6a); std::cout << "**** iterateDown(): " << d6.count() << " ms\n"; std::cout << " " << numPoints << " points\n"; auto t7a = std::chrono::high_resolution_clock::now(); covariant(coll); auto t7b = std::chrono::high_resolution_clock::now(); auto d7 = std::chrono::duration(t7b-t7a); std::cout << "**** covariant():): " << d7.count() << " ms\n"; auto t8a = std::chrono::high_resolution_clock::now(); cleanColl(coll); auto t8b = std::chrono::high_resolution_clock::now(); auto d8 = std::chrono::duration(t8b-t8a); std::cout << "**** cleanColl(): " << d8.count() << " ms\n"; auto d = std::chrono::duration(t8b-t1a); std::cout << "---------- "; TrackNew::status(); if (numLoops > 0) { ++numMeasured; data["a: initColl(): "] += d1; data["b: cleanColl(): "] += d8; data["c: iterate(): "] += d5; data["d: iterateDown(): "] += d6; data["e: shuffleAndMod(): "] += d2; data["f: sort(): "] += d3; data["g: copy() "] += d4; data["h: covariant(): "] += d7; data["i: ALL: "] += d; } } std::cout << "***********************************************\n"; for (const auto& d : data) { std::cout << " " << d.first << d.second.count() / numMeasured << "ms\n"; } std::cout << "sizeof(GOType): " << sizeof(GOType) << '\n'; }