#include #include #include #include #include template class QuickSorterMT { public: template QuickSorterMT(C cmp, int max_depth) : cmp(cmp), max_depth(max_depth) { static_assert(std::is_same, bool>(), "C must be a function that returns a bool"); } auto sort(std::vector &data) -> void { std::span sortable(data); qsort(sortable, 0, max_depth); } private: auto parition(std::span &data) -> std::pair, std::span> { std::vector buf(data); auto pivot = buf.begin(); std::advance(pivot, std::distance(buf.begin(), buf.end()) / 2); auto lefti = buf.begin(); auto righti = buf.end(); while (1) { for (; cmp(*lefti, *pivot); lefti++); for (; !cmp(*righti, *pivot); righti--); if (lefti >= righti) { break; } std::swap(lefti, righti); } std::move(buf.begin(), buf.end(), data.begin()); return {std::span(data.begin(), lefti), std::span(lefti, data.end())}; } auto qsort(std::span &data, int depth, const int &mdepth) -> void { if (std::distance(data.begin(), data.end()) <= 1) { return; } else if (std::distance(data.begin(), data.end()) == 2) { if (cmp(data[1], data[0])) { std::swap(data[0], data[1]); return; } } // Determine mid of data auto mid = data.begin(); std::advance(mid, std::distance(data.begin(), data.end()) / 2); // Generate left and right view on data (no copies are made here) std::span left(data.begin(), mid); std::span right(mid, data.end()); if (depth < mdepth) { std::thread left_thread([&]() { qsort(left, depth + 1, mdepth); }); std::thread right_thread([&]() { qsort(right, depth + 1, mdepth); }); left_thread.join(); right_thread.join(); } else { qsort(left, depth + 1, mdepth); qsort(right, depth + 1, mdepth); } } std::function cmp; const int max_depth; };