Как преобразовать std::function в указатель функции?

Мне нужно использовать 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));
}

Почему бы не std::sort с лямбдой?

Retired Ninja 27.11.2022 03:46

C qsort не приспособлен для обработки функций сравнения с отслеживанием состояния, и в любом случае это ужасно небезопасно. В более общем смысле, то, что является хорошей практикой в ​​C, часто является ужасной практикой в ​​C++, и этот код демонстрирует некоторые из них. Raw new[] вместо std::vector, qsort вместо std::sort, просто надеясь, что плоская memcopy qsort не сломает систему типов C++... нет ничего невозможного в том, чтобы писать код таким образом, который работает, если вы будете предельно осторожны и хорошо разбирается в языковых правилах, но он излишне сложен, подвержен ошибкам и труден в обслуживании. Почему так?

Wintermute 27.11.2022 03:54

Потому что std::sort и stl не разрешены в моем курсе по структуре данных. Я не знаю, почему...

zhaozk 27.11.2022 03:58

@zhaozk вы используете std::function (которая является частью стандартной библиотеки) и лямбда-выражения, но вам не разрешено использовать std::sort()? В этом нет смысла, это глупое ограничение, которое ничему полезному не учит. Вам нужно поговорить с учителем. Вы не можете использовать std::function с std::qsort(), они просто несовместимы. Ни одна из них не является захватом лямбды, если на то пошло. Незахватывающая лямбда совместима с std::qsort(), но это не решает вашу задачу. Однако qsort_s() (нет std::) решит вашу задачу.

Remy Lebeau 27.11.2022 04:26

Меня бесконечно раздражает, когда люди учат "C++" таким образом. Как будто они застряли в 1985 году и так и не написали ни строчки реального производственного кода. C-с-классами было достаточно для моего дедушки, это достаточно хорошо для меня, такая атмосфера. Эти ребята не имеют права пытаться кого-то учить. Кровавый ад.

Wintermute 27.11.2022 14:04
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
85
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы должны использовать 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], вам нужно заменить вычитание чем-то, что не подвержено переполнению.)

Другие вопросы по теме