ошибка: ни один оператор "<" не соответствует этим операндам - PullRequest
1 голос
/ 06 июля 2019

Я получаю ошибку:

/usr/include/c++/7/bits/stl_function.h:386: 
error: no operator "<" matches these operands
operand types are: const QVector3D < const QVector3D
{ return __x < __y; }

Я использую QVector3D с std::set и std::hypot. Есть ли какой-нибудь подход к реализации перегруженного operator< для QVector3D, чтобы иметь возможность использовать его в моем коде?

std::pair<QVector3D, QVector3D> NearestNeighbor::nearest_pair(std::vector<QVector3D> points)
{
     // // Sort by X axis
     std::sort( points.begin(), points.end(), [](QVector3D const &a, QVector3D const &b) { return a.x() < b.x(); } );

     // // First and last points from `point` that are currently in the "band".
     auto first = points.cbegin();
     auto last = first + 1;

     // // The two closest points we've found so far:
     auto first_point = *first;
     auto second_point = *last;

     std::set<QVector3D> band{ *first, *last };

     // // Lambda function to find distance
     auto dist = [] (QVector3D const &a, QVector3D const &b) { return std::hypot(a.x() - b.x(), a.y() - b.y()); };

     float d = dist(*first, *last);

     while (++last != points.end()) {
         while (last->x() - first->x() > d) {
             band.erase(*first);
             ++first;
         }

         auto begin = band.lower_bound({ 0, last->y() - d, 0 });
         auto end   = band.upper_bound({ 0, last->y() + d, 0 });

         assert(std::distance(begin, end) <= 6);

         for (auto p = begin; p != end; ++p) {
             if (d > dist(*p, *last)) {
                 first_point = *p;
                 second_point = *last;
                 d = dist(first_point, second_point);
             }
         }

         band.insert(*last);
     }
     return std::make_pair(first_point, second_point);
}

UPDATE

С помощью @CuriouslyRecurringThoughts, проблема решена заменой:

std::set<QVector3D> band{ *first, *last };

с:

auto customComparator = [](QVector3D const &a, QVector3D const &b) { return a.y() < b.y(); };
std::set<QVector3D, decltype (customComparator)> band({ *first, *last }, customComparator);

Также я могу сделать это:

auto customComparator = [](QVector3D const &a, QVector3D const &b) { return a.y() < b.y(); };
std::set<QVector3D, decltype (customComparator)> band(customComparator);
band.insert(*first);
band.insert(*last);

1 Ответ

1 голос
/ 06 июля 2019

Я думаю, у вас есть различные возможности.Да, вы можете перегрузить operator<, как указано в комментарии, но я бы посоветовал против этого: вам нужна особая функция сравнения для этого конкретного варианта использования, возможно, где-то еще вам понадобится другой порядок.Если отношение порядка для типа не очевидно, я бы предложил избегать перегрузки оператора.

Вы можете предоставить пользовательскую функцию сравнения, как в следующем

auto customComparator = [](QVector3D const &a, QVector3D const &b) { return a.x() < b.x(); };

std::set<QVector3D, decltype(customComparator)> set(customComparator);

set.insert(*first)

Для меня неясно, чтонабор band пытается достичь, но поскольку вы вызываете верхнюю и нижнюю границу для координаты y(), возможно, вы захотите сравнить с y(), но это означает, что две точки с одинаковым y() будут считатьсяравно и std::set не допускает дублирования.

В противном случае вы можете посмотреть на std::unordered_set (https://en.cppreference.com/w/cpp/container/unordered_set), который не требует упорядочения, а только того, что элемент имеет operator == и хэшфункция.

Редактировать: другая альтернатива: вы можете использовать std::vector, а затем использовать свободную функцию std::lower_bound и std::upper_bound с пользовательской функцией сравнения, см. https://en.cppreference.com/w/cpp/algorithm/lower_bound

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...