Как использовать функцию-член с std::bsearch

У меня есть класс С++, но я также использую C низкого уровня и мне нужно использовать функцию bsearch. Последний аргумент bsearch — это функция сравнения, и я хочу реализовать указанную функцию таким образом, чтобы она могла получить доступ к константным закрытым переменным класса.

Проблема в том, что если я сделаю функцию сравнения функцией-членом, она не будет работать, потому что она не будет преобразована в обычный указатель на функцию. Если я создам функцию, не являющуюся членом, я могу передать ее bsearch, но не смогу получить доступ к закрытым переменным класса.

Что делать?

пример: введите здесь описание изображения

3 означает, что есть 3 элемента. 16,32,56 — это байты смещения. Мне нужен bsearch для поиска актеров. Я ищу в массиве смещений. указатель для вычисления местоположений в функции сравнения.actorFIle является частной переменной класса.


person sparrow2    schedule 10.10.2017    source источник
comment
@StoryTeller Спасибо за быстрый ответ. Разве это не может быть сделано с помощью чистого bsearch? Также я мельком увидел более низкий уровень, и ему также нужна функция cmp, чем в этом случае он отличается от bsearch?   -  person sparrow2    schedule 10.10.2017
comment
std::lower_bound может принимать любой функтор (функцию или объект, для которого определен оператор(), включая лямбда-выражения). А с объектом вы можете хранить любые переменные, необходимые для сравнения.   -  person kmdreko    schedule 10.10.2017
comment
ваша функция сравнения может быть бесплатной, если вы предоставите геттер для частного члена. Частные члены не доступны для доступа извне класса, если вам нужно получить к нему доступ, сделайте его общедоступным или предоставьте способ доступа к нему.   -  person 463035818_is_not_a_number    schedule 10.10.2017
comment
@ tobi303 tobi303 - бесплатной функции по-прежнему нужен экземпляр класса. С bsearch пришлось бы прибегать к глобальным переменным. Это запах.   -  person StoryTeller - Unslander Monica    schedule 10.10.2017
comment
@StoryTeller Я не понимаю, бесплатной функции все еще нужен экземпляр класса? бесплатная функция будет int compare(const void*,const void*), а экземпляры передаются как параметры. кстати я ни в коем случае не пытаюсь защищаться с помощью bsearch   -  person 463035818_is_not_a_number    schedule 10.10.2017
comment
@ tobi303 - Проблема ОП, как я понимаю, заключается в том, что их класс вызывает bsearch некоторые вещи низкого уровня C. Не то, чтобы bsearch использовался для сортировки экземпляров класса (что было бы ужасно).   -  person StoryTeller - Unslander Monica    schedule 10.10.2017
comment
@StoryTeller а, ладно, кажется, я неправильно понял вопрос   -  person 463035818_is_not_a_number    schedule 10.10.2017
comment
@ tobi303 - На самом деле, ваша точка зрения заставляет меня думать, что я, возможно, неправильно ее понял. Я исправил формулировку вопроса, но она все еще может быть неясной.   -  person StoryTeller - Unslander Monica    schedule 10.10.2017
comment
@StoryTeller без кода всегда сложно сказать...   -  person 463035818_is_not_a_number    schedule 10.10.2017
comment
предоставьте минимальный воспроизводимый пример. Вопрос не ясен на 100%. Что вы хотите искать? Как вы думаете, зачем вам нужен доступ к закрытому члену?   -  person 463035818_is_not_a_number    schedule 10.10.2017


Ответы (2)


Решение состоит в том, чтобы отказаться от библиотечной функции C и использовать C++ так, как он предназначен для использования. В стандартной библиотеке C++ также есть функция поиска утилит, она называется std::lower_bound. И он принимает общие объекты, подобные функциям, а не только обычные указатели на функции.

Это позволяет вам вызывать его с помощью лямбда-выражения, которое фиксирует ваш класс:

std::lower_bound(start, finish, value, [this] (auto const& lhs, auto const& rhs) {
                 /* Compare and utilize anything this can point to*/ });
person StoryTeller - Unslander Monica    schedule 10.10.2017
comment
было бы лучше использовать lower_bound, но я действительно привязан к bsearch. - person sparrow2; 10.10.2017
comment
@sparrow2 - я действительно не понимаю, как это сделать. bsearch работает только с простыми массивами, lower_bound работает также с простыми массивами C. - person StoryTeller - Unslander Monica; 10.10.2017
comment
@sparrow2 Ты не можешь съесть свой торт и съесть его. bsearch — это функция C, которая ничего не знает о классах и функциях-членах. - person David Haim; 10.10.2017
comment
@StoryTeller Я запускаю bsearch по смещениям, в примере 16,32,56, но в функции сравнения я сравниваю реальную информацию, поэтому мне нужен actFile, чтобы вычислить, где находится реальная информация. - person sparrow2; 10.10.2017
comment
@sparrow2 - В вашем посте нет примера, в нем есть диаграмма и махание рукой. Правильный пример (минимально воспроизводимый пример). Будет иметь образец кода C и C++, который показывает, что вы пытаетесь сделать. Мы не собираемся гадать, как вам помочь. Вы должны сказать нам. - person StoryTeller - Unslander Monica; 10.10.2017

Если вы действительно привязаны к bsearch, просто используйте свою функцию-член внутри функции, не являющейся членом. Следовательно, вам не нужно получать доступ к закрытым членам.

/* Create global variable to use in compare proc*/
actors_data_base* cmp_data_base = NULL;

/* Write compare routine like */
int cmp_proc(const void * a, const void * b)
{
    size_t a_offset = static_cast<size_t>(a);
    size_t b_offset = static_cast<size_t>(b);
    return cmp_data_base->compare_actors(a_offset, b_offset);
}


/* Set global pointer and use bsearch */
actors_data_base = &my_data_base;
bsearch(&my_value, array, size, sizeof(size_t), cmp_proc);

Определенно, это некрасиво из-за использования глобальной переменной. Но это единственный способ передать контекст для сравнения proc. Вы можете подумать об использовании локального хранилища потоков, чтобы избежать проблем с потоками (cmp_proc нельзя использовать одновременно из-за глобальной переменной)

Следовательно, вам было бы намного лучше использовать std::lower_bound.

person ivaigult    schedule 10.10.2017
comment
Компилятор не позволит мне использовать функцию-член внутри функции-члена в файле класса, если у меня нет экземпляра и вызвать метод-член этого экземпляра - person sparrow2; 10.10.2017
comment
Позвольте мне уточнить. Я добавлю пример. - person ivaigult; 10.10.2017