Я хочу использовать std::upper_bound
, чтобы найти диапазон объектов в некотором контейнере, которые меньше или равны предоставленному значению. Это делает его хорошим простым однострочником!
Проблема в том, что меня интересует только сравнение с конкретным примитивным членом класса. Сортировка контейнера не проблема, но когда я хочу использовать std::upper_bound
, мне нужно предоставить объект для сравнения, чтобы функция работала.
Для MCVE, предположим, что у меня есть группа людей, и я хочу найти итератор для:
struct Person {
int age;
double height;
Person(int age, double height) : age(age), height(height) { }
};
int main() {
vector<Person> people = {
Person(5, 12.3),
Person(42, 9.6),
Person(38, 18.4),
Person(31, 8.5)
};
auto sorter = [](const Person& a, const Person& b) {
return a.height < b.height;
};
std::sort(people.begin(), people.end(), sorter);
// All I care about is comparing against this number
// Instead... I have to create a whole new struct
//double cutoff = 10.0;
Person cutoff(123, 10.0);
auto it = std::upper_bound(people.begin(), people.end(), cutoff, sorter);
// Do stuff with 'it' here
}
Проблема, с которой я столкнулся, заключается в том, что мне нужно создать экземпляр всего объекта просто для использования std::upper_bound
, как я делаю в коде выше. У меня не может быть «компаратора против ценности, которую я предоставляю». Это делает его очень раздражающим, потому что объекты, с которыми я сравниваю, не могут легко появиться, не выполняя при этом много работы.
Существуют ли какие-либо жизнеспособные стратегии, позволяющие обойти это, что приведет к созданию самого чистого и компактного кода, который я могу найти? Например, было бы неплохо, если бы я мог сделать (для MCVE):
auto cutoffCompare = [](const Person& p, const double height) {
return p.height < height;
};
// Doesn't exist (AFAIK?)
auto it = std::upper_bound(people.begin(), people.end(), cutoff, sorter, cutoffCompare);
Из-за того, что я нахожусь в «горячей точке» программы, где мне важнее производительность, я не могу сделать что-то вроде преобразования объектов в примитивный тип и затем выполнить upper_bound
в этом новом списке. Я могу создать совершенно новый объект и использовать его как пустышку, но потом я добавлю раздражающее количество кода, чтобы сделать что-то очень простое. Я застрял в создании объекта? Или я должен бросить свой собственный upper_bound?