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
这太冗长了。有没有更简洁的方法?
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);
我正在练习算法教科书和现代 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
这太冗长了。有没有更简洁的方法?
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);