#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> { auto pivot = data.begin(); std::advance(pivot, std::distance(data.begin(), data.end()) / 2); auto lefti = data.begin(); auto righti = data.end() - 1; while (1) { for (; cmp((*lefti), (*pivot)); lefti++); for (; !cmp((*righti), (*pivot)); righti--); if (lefti >= righti) { break; } std::swap(*lefti, *righti); } return {std::span(data.begin(), pivot - 1), std::span(pivot + 1, 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; } } auto res = parition(data); auto &left = res.first; auto &right = res.second; 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; };