Я практикую учебник по алгоритмам и современное кодирование на 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
@ConstantinosGlynos: Вы, вероятно, не хотите, чтобы frozenca::cout
«работал» где-то еще в программе.
@DavisHerring В моем коде используется пространство имен std; действителен только в блоке пространства имен Frozenca { }
Показанный код находится внутри заголовка (поскольку он определяет шаблоны)?
@Sebastian Код находится внутри заголовка, но включение его из другого файла неявно не объявляет использование пространства имен std; в этом файле, вы можете попробовать. Если я перемещаюсь, используя пространство имен std; за пределами блока namespace { } , тогда, конечно, это большая проблема
@frozenca: он по-прежнему позволяет членам std
быть доступ к через этому пространству имен в другом месте (надеюсь, эта ссылка будет работать, когда Wandbox будет исправлен).
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);
Этот вопрос, вероятно, относится к обзору кода. Кроме того,
using namespace std
допустимо, когда оно заключено в контролируемую область. Когда вы видите его в глобальном пространстве имен, это может вызвать проблемы.