I'm practicing Algorithms textbook and modern C coding.
I wrote a brief test that verifies sorting functions as the following:
(I know using namespace std;
is discouraged in production, so please don't advice on that)
namespace frozenca {
using namespace std;
template <ranges::input_range R>
void print(R&& r, ostream& os = cout) {
for (auto elem : r) {
os << elem << ' ';
}
os << '\n';
}
mt19937 gen(random_device{}());
template <typename F, ranges::forward_range R = vector<int>> requires regular_invocable<F, R>
void verify_sorting(F&& f, int num_trials = 1'000, int max_length = 1'000) {
uniform_int_distribution<> len_dist(0, max_length);
for (int i = 0; i < num_trials; i) {
R v;
int n = len_dist(gen);
generate_n(back_inserter(v), n, ref(gen));
f(v);
if (!ranges::is_sorted(v)) {
throw runtime_error("Sorting verification failed");
}
}
std::cout << "Sorting verification success!\n";
}
} // namespace frozenca
and I wrote an insertion sort code like this:
namespace frozenca {
using namespace std;
struct insertion_sort_func {
template <ranges::bidirectional_range R = vector<int>, typename F = ranges::greater>
constexpr void operator()(R&& r, F comp = {}) const {
if (ranges::empty(r)) return;
for (auto i = next(begin(r)); i != end(r); i) {
auto key = *i;
auto j = i;
while (j != begin(r) && comp(*prev(j), key)) {
iter_swap(prev(j), j);
--j;
}
*j = key;
}
}
};
inline constexpr insertion_sort_func insertion_sort{};
} // namespace frozenca
And here is my test code, which works nicely:
int main() {
namespace fc = frozenca;
std::vector<int> v{5, 2, 4, 6, 1, 3};
fc::insertion_sort(v);
fc::print(v); // outputs "1 2 3 4 5 6"
fc::verify_sorting(std::ranges::sort); // outputs "Sorting verification success!"
fc::verify_sorting(fc::insertion_sort); // outputs "Sorting verification success!"
}
My verify_sorting
function tests the sorting function for type std::vector<int>
by default. Of course it can test other std::ranges::forward_range
, but it becomes extremely verbose. For testing std::vector<float>
, what I checked working is like this:
fc::verify_sorting<decltype(fc::insertion_sort), std::vector<float>>
(std::forward<decltype(fc::insertion_sort)>(fc::insertion_sort));
// OK
This is way too verbose. Is there any less verbose way?
Running code: https://wandbox.org/permlink/4UPLxeJxDlOkXcN1
CodePudding user response:
This is way too verbose. Is there any less verbose way?
Just change the order of template parameters
template <ranges::forward_range R = vector<int>, typename F>
requires regular_invocable<F, R>
void verify_sorting(F&& f, /* */);
Then you can just invoke like this
fc::verify_sorting(std::ranges::sort);
fc::verify_sorting(fc::insertion_sort);
fc::verify_sorting<std::vector<float>>(fc::insertion_sort);