Мне нужно использовать std::qsort()
для сортировки массива nd-Point. Но я получаю сообщение об ошибке:
неизвестное преобразование из 'function<int (const void *, const void )>' в '__compar_fn_t' (он же 'int ()(const void *, const void *)')`
Как это решить или отсортировать по директории другим методом?
#include <iostream>
#include <functional>
int d, n;
struct Point {
int *x;
Point() : x(new int[d]) {};
};
std::function<int(const void *, const void *)> make_cmp(int dir) {
return [dir](const void *a, const void *b)->int {
auto a_ = (Point *)a;
auto b_ = (Point *)b;
return a_->x[dir] - b_->x[dir];
};
}
void sort_points(Point *value, int length, int dir) {
std::qsort(value, length, sizeof(Point), make_cmp(dir));
}
C qsort
не приспособлен для обработки функций сравнения с отслеживанием состояния, и в любом случае это ужасно небезопасно. В более общем смысле, то, что является хорошей практикой в C, часто является ужасной практикой в C++, и этот код демонстрирует некоторые из них. Raw new[] вместо std::vector
, qsort
вместо std::sort
, просто надеясь, что плоская memcopy qsort
не сломает систему типов C++... нет ничего невозможного в том, чтобы писать код таким образом, который работает, если вы будете предельно осторожны и хорошо разбирается в языковых правилах, но он излишне сложен, подвержен ошибкам и труден в обслуживании. Почему так?
Потому что std::sort
и stl не разрешены в моем курсе по структуре данных. Я не знаю, почему...
@zhaozk вы используете std::function
(которая является частью стандартной библиотеки) и лямбда-выражения, но вам не разрешено использовать std::sort()
? В этом нет смысла, это глупое ограничение, которое ничему полезному не учит. Вам нужно поговорить с учителем. Вы не можете использовать std::function
с std::qsort()
, они просто несовместимы. Ни одна из них не является захватом лямбды, если на то пошло. Незахватывающая лямбда совместима с std::qsort()
, но это не решает вашу задачу. Однако qsort_s()
(нет std::
) решит вашу задачу.
Меня бесконечно раздражает, когда люди учат "C++" таким образом. Как будто они застряли в 1985 году и так и не написали ни строчки реального производственного кода. C-с-классами было достаточно для моего дедушки, это достаточно хорошо для меня, такая атмосфера. Эти ребята не имеют права пытаться кого-то учить. Кровавый ад.
Если вы должны использовать std::qsort
, то вы в основном пишете на C, а не на C++. Это может быть одна из немногих ситуаций, когда глобальная переменная является наименее плохим подходом.
static thread_local int dir;
int cmp(const void *a, const void *b) {
auto a_ = (const Point *)a;
auto b_ = (const Point *)b;
return a_->x[dir] - b_->x[dir]; // beware of overflow
}
void sort_points(Point *value, int length, int d) {
dir = d;
std::qsort(value, length, sizeof(Point), cmp);
}
Если это никогда не будет вызываться более чем из одного потока одновременно, вы можете удалить thread_local
.
(Обратите внимание, что если значения могут превышать диапазон [INT_MIN/2, INT_MAX/2]
, вам нужно заменить вычитание чем-то, что не подвержено переполнению.)
Почему бы не
std::sort
с лямбдой?