#c
#c
Вопрос:
У меня есть класс, который включает в себя несколько членов типа double
.
Предположим, мне нужно создать функцию, которая переупорядочивает вектор объектов класса на основе значений одного из членов класса. Итак:
class myClass{
...
public:
double x, y, z;
...
}
void SpecialSort_x(std::vector<myClass>amp; vec) {
// re-order stuff according to values of vec[i].x
...
}
Но теперь я хочу иметь возможность выполнять такое же переупорядочение, но в соответствии со значениями других членов класса ( y
и z
в приведенном выше коде).
Вместо создания еще двух функций, идентичных первой, за исключением того, что все ссылки x
изменены на y
или z
, я хотел бы создать единую полиморфную функцию, которая может изменять порядок вектора в соответствии с любым из членов myClass
.
Каков наилучший способ сделать это?
Комментарии:
1. Почему бы вам просто не использовать
std::sort
с пользовательской функцией сравнения (object)?2. Давайте начнем с вопроса, почему вы не используете
std::sort
.3. Расширение
dyp's comment, use
std::sort` с помощью лямбды.4. @Jon, @ Deduplicator, переупорядочение — это не просто сортировка. Для этого требуется больше, чем одна функция сравнения (насколько я могу судить). Кроме того, я хотел бы, чтобы функция в будущем делала больше, чем просто переупорядочивала. Возможно, возвращает некоторые значения на основе значений конкретного рассматриваемого члена класса.
5.
std::sort
это правильный путь, но чтобы ответить на ваш заданный вопрос, вы могли бы использовать аргумент типа указатель на членdouble myClass::*
.
Ответ №1:
Вы можете использовать std::sort
, в сочетании с лямбдой и указателем на член, таким образом:
#include <vector>
#include <algorithm>
class MyClass
{
public:
double x, y, z;
};
typedef double MyClass::* Field;
void specialSort(std::vector<MyClass>amp; vec, Field field)
{
std::sort(vec.begin(), vec.end(), [field](const MyClass amp; a, const MyClass amp; b) -> bool
{
return a.*field < b.*field;
});
}
int main()
{
std::vector<MyClass> vec;
Field member = amp;MyClass::x;
specialSort(vec, member);
return 0;
}
И вы также можете создать шаблон для сортировки с помощью:
template<class T>
void specialSort(std::vector<T>amp; vec, double T::* field)
{
std::sort(vec.begin(), vec.end(), [field](const Tamp; a, const Tamp; b) -> bool
{
return a.*field < b.*field;
});
}
Ответ №2:
Я согласен со всеми, предлагающими альтернативные подходы, учитывая описание проблемы здесь.
Однако, если вам когда-нибудь действительно понадобится получить доступ к члену класса, выбранному во время выполнения, вы можете использовать тип указателя на член. Однако обычно существует более элегантный способ добиться желаемого эффекта.
Например:
#include <iostream>
#include <vector>
struct X {
double a;
double b;
double c;
};
void operate_on_member(const Xamp; x, double X::*pm)
{
std::cout << x.*pm << 'n';
}
int main()
{
std::vector<X> xs {
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
for (const autoamp; x : xs)
operate_on_member(x, amp;X::a);
for (const autoamp; x : xs)
operate_on_member(x, amp;X::b);
for (const autoamp; x : xs)
operate_on_member(x, amp;X::c);
}