функция сравнения для upper_bound/lower_bound

Я хочу найти первый элемент в отсортированном векторе, поле которого меньше некоторого значения x.
Мне нужно предоставить функцию сравнения, которая сравнивает 'x' с внутренним значением в MyClass, но я не могу определить объявление функции.
Могу ли я просто перегрузить '‹', но как мне это сделать, когда аргументы '&MyClass' и 'float'?

 float x;
 std::vector< MyClass >::iterator last = std::upper_bound(myClass.begin(),myClass.end(),x);

person Martin Beckett    schedule 15.05.2009    source источник


Ответы (4)


Какую функцию вы передали алгоритму сортировки? Вы должны иметь возможность использовать один и тот же для upper_bound и lower_bound.

Самый простой способ заставить сравнение работать — создать фиктивный объект с ключевым полем, установленным в значение вашего поиска. Тогда сравнение всегда будет между подобными объектами.

Редактировать: Если по какой-то причине вы не можете получить фиктивный объект с правильным значением сравнения, вы можете создать функтор сравнения. Функтор может предоставить три перегрузки для operator() :

struct MyClassLessThan
{
    bool operator() (const MyClass & left, const MyClass & right)
    {
        return left.key < right.key;
    }
    bool operator() (const MyClass & left, float right)
    {
        return left.key < right;
    }
    bool operator() (float left, const MyClass & right)
    {
        return left < right.key;
    }
};

Как видите, это долгий путь.

person Mark Ransom    schedule 15.05.2009
comment
В этом была проблема, функция сортировки принимает две константные ссылки на объекты MyClass. Функция поиска должна принимать MyClass и число с плавающей запятой. Та же проблема с использованием bind2nd() - person Martin Beckett; 15.05.2009
comment
operator() для сравнения вещей - почему я не подумал об этом !!! Чем больше я использую STL, тем больше я люблю Python. благодарю вас - person Martin Beckett; 15.05.2009
comment
@chmike, да, конечно. Спасибо. Интересно, почему так долго никто не замечал? - person Mark Ransom; 05.12.2012

Вы можете улучшить решение Марка, создав статический экземпляр MyClassLessThan в MyClass.

class CMyClass 
{
   static struct _CompareFloatField
   {
      bool operator() (const MyClass & left, float right) //...
      // ...
   } CompareFloatField;
};

Таким образом, вы можете вызвать lower_bound следующим образом:

std::lower_bound(coll.begin(), coll.end(), target, CMyClass::CompareFloatField);

Это делает его немного более читаемым

person Ghostrider    schedule 24.03.2010
comment
Мне по-прежнему нужен фиктивный объект и оператор () для каждого члена, но ваш яснее читает намерение - спасибо - person Martin Beckett; 24.03.2010

Передайте лямбда-функцию в upper_bound

 float x;
 MyClass target;
 target.x_ = x;
 std::vector< MyClass >::iterator last = 
 std::upper_bound(myClass.begin(),myClass.end(),target, 
 [](const MyClass& a, const MyClass& b){return a.x_ < b.x_;});
person bigdata2    schedule 07.06.2020

Я думаю, что вам нужно std::bind2nd(std::less<MyClass>(), x). Но, конечно же, для MyClass должен быть определен оператор‹.

Изменить: о, и я думаю, вам понадобится конструктор для MyClass, который принимает только число с плавающей запятой, чтобы его можно было неявно преобразовать. Тем не менее, может быть лучший способ сделать это.

person Borbus    schedule 15.05.2009