C ++输入模板参数的简洁方式

C++ less verbose way to input template argument

我正在练习算法教科书和现代 C++ 编码。 我写了一个简短的测试来验证排序功能如下: (我知道 using namespace std; 在生产中不鼓励,所以请不要就此提出建议)

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

我写了一个这样的插入排序代码:

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

这是我的测试代码,效果很好:


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!"

}

我的 verify_sorting 函数默认测试类型 std::vector<int> 的排序函数。当然它可以测试其他 std::ranges::forward_range,但它变得非常冗长。为了测试 std::vector<float>,我检查的工作是这样的:

fc::verify_sorting<decltype(fc::insertion_sort), std::vector<float>>
(std::forward<decltype(fc::insertion_sort)>(fc::insertion_sort));
// OK

这太冗长了。有没有更简洁的方法?

运行代码:https://wandbox.org/permlink/4UPLxeJxDlOkXcN1

This is way too verbose. Is there any less verbose way?

只需更改模板参数的顺序

template <ranges::forward_range R = vector<int>, typename F> 
  requires regular_invocable<F, R>
void verify_sorting(F&& f,  /* */);

然后你就可以像这样调用

fc::verify_sorting(std::ranges::sort);
fc::verify_sorting(fc::insertion_sort);
fc::verify_sorting<std::vector<float>>(fc::insertion_sort);

Demo