Я хочу использовать функцию nth_element
с моей собственной функцией сортировки (которая должна иметь доступ к данным объекта) внутри класса. В настоящее время я делаю следующее:
class Foo
{
public:
glm::vec3 *points;
int nmbPoints;
bool idxPointCompareX(int a, int b);
void bar();
}
bool Foo::idxPointCompareX(int a, int b)
{return points[a].x < points[b].x;)
void Foo::bar()
{
stl::vector<int> idxPointList;
for(int i = 0; i < nmbPoints; i++) idxPointList.push_back(i);
stl::nth_element(idxPointList.first(),idxPointList.first()+nmbPoints/2,idxPointList.end(), idxPointCompareX);
}
Конечно, это не сработало, и я получил ошибку: «должна быть вызвана ссылка на нестатическую функцию-член». После этого я посмотрел на Ссылка на нестатическую функцию-член должна быть вызвана, Как инициализировать std::function
с функцией-членом? и некоторые другие вопросы здесь. Я понимаю, почему это не сработало, но я не уверен, как это решить.
Может кто-нибудь мне помочь и подсказать, как решить эту проблему?
Чтобы получить адрес функции-члена, вам нужно использовать правильный синтаксис, т.е. &Foo::idxPointCompareX
не просто idxPointCompareX
Но вам также нужно Foo
объект для вызова функции, поэтому вам необходимо привязать его к ней. Предположительно вы хотите позвонить на this
чтобы вы могли использовать std::bind
:
using namespace std::placeholders;
stl::nth_element(begin, end, std::bind(&Foo::idxPointCompareX, this, _1, _2));
Или проще, используйте лямбда-функцию:
stl::nth_element(begin, end,
[this](int a, int b) { return idxPointCompareX(a, b);}
);
Это создает лямбда-функцию, которая захватывает this
и передает свои аргументы в функцию idxPointCompareX на захваченном this
указатель.
idxPointCompareX
является функцией-членом, т.е. она не может быть вызвана без какой-либо ссылки на Foo
объект. Глядя на его определение, кажется, что он не должен быть членом, поскольку он чисто определен в терминах своих аргументов.
Вы могли бы сделать это static
функция (то есть «функция класса») или свободная функция, а затем передать его std::nth_element
,
Вы не можете вызвать метод объекта до того, как он будет создан, поэтому у вас есть несколько вариантов здесь:
Сделайте метод статичным
Оставьте конструктор пустым и переместите все в init
метод, в котором вы вызываете часть сравнения
Используйте лямбду
Статический метод:
static bool idxPointCompareX(glm::vec3 a, glm::vec3 b)
{return a.x < b.x;)
Метод инициализации:
Foo::bar()
{
stl::vector<int> idxPointList;
for (int i = 0; i < nmbPoints; i++)
idxPointList.push_back(i);
}
Foo::init()
{
stl::nth_element(idxPointList.first(),
idxPointList.first()+nmbPoints/2,idxPointList.end(),
idxPointCompareX);
}
Lambda:
Foo::bar()
{
stl::vector<int> idxPointList;
for (int i = 0; i < nmbPoints; i++)
idxPointList.push_back(i);
stl::nth_element(idxPointList.first(),
idxPointList.first()+nmbPoints/2,idxPointList.end(),
[](int a, int b){return points[a].x < points[b].x;));
}
Я бы сам пошел на лямбда-версию.