Ошибка при перегрузке оператора <в sf :: Vector

Я хочу использовать std::map с классом sf::Vector2i, но по какой-то причине мне нужен overload < operator. Поскольку карта будет представлять собой сетку 3x3, я придумал следующее, чтобы отсортировать векторы:

inline bool operator <(sf::Vector2i l, sf::Vector2i r)
{
    if (l.x * 3 + l.y < r.x * 3 + r.y) return 1;
    return 0;
}

Но я все равно получаю ошибку C2678

no operator found which takes a left-hand operand of type 'const sf::Vector2i'

Я сделал то же самое со своим пользовательским векторным типом, и он сработал, так что же вызывает эту ошибку?

Редактировать:

Эта перегрузка находится в отдельном файле .cpp. Я просто обернул эту перегрузку в пространство имен sf{}, и она сработала. Почему не работает просто указание sf::Vector2i в параметрах?

это заявлено в заголовке?

user253751 15.06.2018 03:35

В дополнение к иммибису: определение оператора должно быть «видимым» там, где он используется. Обычный способ сделать это: определите его выше для функции, где он вам нужен, или определите его в файле заголовка, который является #included в файле, где он вам нужен.

Scheff's Cat 15.06.2018 07:45
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
66
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Давайте начнем с:

I want to use std::map with sf::Vector2i class, but for some reason I need to overload < operator.

std::map упорядочивает свое содержимое по ключам, что требует знания порядка расположения ключей (предположительно sf::Vector2i). По умолчанию порядок расположения ключей определяется operator <. Это означает, что карта вызывает operator<(const sf::Vector21&, const sf::Vector21&), чтобы определить, меньше ли один ключ, чем другой. Следовательно, этот оператор должен быть где-то определен.

Если вас не интересует этот порядок, вы можете вместо этого попробовать unordered_map.

I just wrapped this overload in a namespace sf{} and it worked. Why doesn't it work by just specifying sf::Vector2i in the parameters?

Вероятно, это результат правила поиска для зависимых имен. Помните тот звонок в operator<? Это будет сделано где-то глубоко внутри шаблонов, а типы его аргументов зависят от параметров шаблона. Соответствующим следствием этого является то, что компилятор будет искать объявления, видимые из определения шаблона (глубоко в файлах заголовков), а также все, что найдено с помощью поиска, зависимого от аргументов (ADL). Ваша перегрузка не видна из определения шаблона (да и не должна), поэтому ее нужно будет найти с помощью ADL. Однако оба аргумента находятся в пространстве имен sf, поэтому ADL просматривает только пространство имен sf. Следовательно, компилятор может найти перегрузку в пространстве имен sf, но не где-либо еще.

Это чаще встречается, когда аргументы находятся в пространстве имен std, но должно применяться и здесь. (Кое-что из этого для меня в новинку, поэтому я мог перепутать некоторые детали.) Главный вывод заключается в том, что попытка переопределить операторы, действующие только на классы в другом пространстве имен, часто терпит неудачу.

Хорошая новость в том, что вы не застряли. std::map принимает более двух параметров шаблона. Третий позволяет указать, как нужно сравнивать ключи. Прочтите эту тему и посмотрите, как далеко вы можете продвинуться.

Фактически, ваш оператор не принимает константу Vector2i. Константа важна!

Почему в этом случае необходимо использовать const?

John 15.06.2018 21:49

Извините, это не так. Я пропустил вашу правку, что он работает в пространстве имен sf. Я согласен с @JaMiT, что это, вероятно, проблема с поиском имени. Обычно бесплатные функции, операторы и т. д., Которые являются «частью» интерфейса класса, должны быть объявлены в том же пространстве имен. АДЛ сделает все остальное. Объявляя operator <, вы расширяете интерфейс Vector2i и должны поместить его в то же пространство имен.

ravnsgaard 15.06.2018 22:34

const был бы важен, если бы параметр передавался по ссылке вместо значения. (Этот ответ тоже был одной из моих первых мыслей.) Кстати говоря, передача по ссылке const вместо value была бы хорошей идеей, @John.

JaMiT 15.06.2018 23:20

@JaMiT Да, именно поэтому я в первую очередь опубликовал ответ. Я слишком быстро прочитал описание. Однако проголосовал за ваш ответ. Я думаю, это касается самого важного.

ravnsgaard 15.06.2018 23:21

Надеюсь, я не произвел неправильного впечатления. Я не объяснял тебе, @ravnsgaard, столько, сколько объяснил случайному человеку, читающему эти комментарии. ;)

JaMiT 15.06.2018 23:31

Другие вопросы по теме