Сравнивая два экземпляра следующей структуры, я получаю сообщение об ошибке:
struct MyStruct1 {
MyStruct1(const MyStruct2 &_my_struct_2, const int _an_int = -1) :
my_struct_2(_my_struct_2),
an_int(_an_int)
{}
std::string toString() const;
MyStruct2 my_struct_2;
int an_int;
};
Ошибка:
ошибка C2678: двоичный '==': не найден оператор, который принимает левый операнд типа 'myproj :: MyStruct1' (или нет приемлемого преобразования)
Зачем?
c++
struct
comparison-operators
Джонатан
источник
источник
struct
s на равенство? И если вам нужен простой способ,memcmp
ваши структуры всегда не содержат указателей.memcmp
не работает с не-членами POD (например,std::string
) и заполненными структурами.==
оператор --- с семантикой, которая почти никогда не бывает той, которая нужна. (И они не предоставляют средств для его переопределения, поэтому вам придется использовать функцию-член). «Современные» языки, которые я знаю, также не предоставляют семантику значений, поэтому вы вынуждены использовать указатели, даже если они не подходят.operator=
(даже если он часто делает неправильные вещи) по причинам совместимости с C. Однако для совместимости с C не требуетсяoperator==
. Во всем мире я предпочитаю то, что делает C ++, а не Java. (Я не знаю C #, так что, может быть, так лучше.)= default
!В C ++ 20 введены сравнения по умолчанию, также известные как «космический корабль»
operator<=>
, которые позволяют запрашивать<
/<=
/==
/!=
/>=
/ и / или>
операторы, созданные компилятором, с очевидной / наивной (?) Реализацией ...... но вы можете настроить это для более сложных ситуаций (обсуждаемых ниже). См. Здесь предложение по языку, которое содержит обоснования и обсуждение. Этот ответ остается актуальным для C ++ 17 и более ранних версий, а также для понимания того, когда следует настраивать реализацию
operator<=>
....Может показаться немного бесполезным для C ++ не стандартизировать это ранее, но часто в структурах / классах есть некоторые элементы данных, которые нужно исключить из сравнения (например, счетчики, кешированные результаты, емкость контейнера, код успешной / ошибки последней операции, курсоры), так как а также решения по бесчисленным вопросам, включая, но не ограничиваясь:
int
члена может очень быстро устранить 99% неравных объектов, в то время какmap<string,string>
член может часто иметь идентичные записи и быть относительно дорогостоящим для сравнения - если значения загружаются во время выполнения, программист может иметь представление о компилятор не можетvector
,list
), и если да, можно ли сортировать их на месте перед сравнением или использовать дополнительную память для сортировки временных контейнеров каждый раз, когда выполняется сравнениеunion
сравниватьoperator==
сами по себе (но могут иметьcompare()
илиoperator<
илиstr()
или геттеры ...)Так что неплохо иметь ошибку, пока вы явно не подумаете о том, что сравнение должно означать для вашей конкретной структуры, вместо того, чтобы позволять ей компилироваться, но не давать значимого результата во время выполнения .
Все , что сказал, что было бы хорошо , если C ++ позволит вам сказать ,
bool operator==() const = default;
когда ты решил «наивный» член-на-член==
испытание было в порядке. То же самое для!=
. Учитывая несколько членов / баз, « по умолчанию»<
,<=
,>
, и>=
реализации кажутся безнадежными , хотя - каскадные на основе порядка декларации возможно , но вряд ли будет то , что хотел, учитывая противоречивые императивы для упорядочения членов (основания быть обязательно перед членами, группировка по доступность, строительство / разрушение до зависимого использования). Чтобы быть более широко полезным, C ++ потребовалась бы новая система аннотаций элементов данных / баз для выбора - это было бы здорово иметь в Стандарте, хотя в идеале в сочетании с созданием определяемого пользователем кода на основе AST ... Я ожидаю Это'Типичная реализация операторов равенства
Правдоподобная реализация
Вполне вероятно, что разумной и эффективной реализацией будет:
Обратите внимание , что это нуждается в
operator==
течениеMyStruct2
слишком.Последствия этой реализации и альтернативы обсуждаются ниже в разделе « Обсуждение особенностей вашего MyStruct1» .
Последовательный подход к ==, <,> <= и т. Д.
std::tuple
Операторы сравнения легко использовать для сравнения экземпляров ваших собственных классов - просто используйте ихstd::tie
для создания кортежей ссылок на поля в желаемом порядке сравнения. Обобщая мой пример отсюда :Когда вы «владеете» (т. Е. Можете редактировать, фактор с корпоративными и сторонними библиотеками) классом, который хотите сравнить, и особенно с готовностью C ++ 14 вывести тип возвращаемого значения функции из
return
оператора, часто лучше добавить " привяжите функцию-член к классу, который вы хотите сравнивать:Тогда приведенные выше сравнения упрощаются до:
Если вам нужен более полный набор операторов сравнения, я предлагаю операторы повышения (поиск
less_than_comparable
). Если по какой-то причине это не подходит, вам может понравиться идея поддержки макросов (онлайн) :... это можно использовать а-ля ...
(Версия для членов C ++ 14 здесь )
Обсуждение особенностей вашего MyStruct1
Есть последствия для выбора предоставить отдельного члена или члена
operator==()
...Отдельно стоящая реализация
Вам нужно принять интересное решение. Поскольку ваш класс может быть неявно построен из a
MyStruct2
, автономнаяbool operator==(const MyStruct2& lhs, const MyStruct2& rhs)
функция / функция , не являющаяся членом, будет поддерживать ...... сначала создать временный
MyStruct1
сmy_myStruct2
, а затем выполнить сравнение. Это определенно оставитMyStruct1::an_int
установленным значение параметра конструктора по умолчанию, равное-1
. В зависимости от того, включают лиan_int
сравнение в реализации Вашегоoperator==
, вMyStruct1
может или не может сравнивать равно а ,MyStruct2
что сам сравнивает равенMyStruct1
«smy_struct_2
члена! Кроме того, создание временного элементаMyStruct1
может быть очень неэффективной операцией, поскольку оно включает в себя копирование существующегоmy_struct2
элемента во временный только для того, чтобы выбросить его после сравнения. (Конечно, вы можете предотвратить это неявное построениеMyStruct1
s для сравнения, создав этот конструкторexplicit
или удалив значение по умолчанию дляan_int
.)Реализация члена
Если вы хотите избежать неявного построения a
MyStruct1
из aMyStruct2
, сделайте оператор сравнения функцией-членом:Обратите внимание на
const
ключевое слово - необходимое только для реализации члена - сообщает компилятору, что сравнение объектов не изменяет их, поэтому его можно разрешить дляconst
объектов.Сравнение видимых представлений
Иногда самый простой способ получить желаемое сравнение - это ...
... которые часто тоже очень дороги - их
string
мучительно создают, чтобы просто выбросить! Для типов со значениями с плавающей запятой сравнение видимых представлений означает, что количество отображаемых цифр определяет допуск, в пределах которого почти равные значения рассматриваются как равные во время сравнения.источник
int cmp(x, y)
илиcompare
функция возвращает отрицательное значениеx < y
, 0 для равенства и положительное значениеx > y
используется в качестве основы для<
,>
,<=
,>=
,==
, и!=
; CRTP очень просто использовать для внедрения всех этих операторов в класс. Я уверен, что опубликовал реализацию в старом ответе, но не смог быстро ее найти.>
,<=
и>=
с точки зрения<
. Вы могли бы также осуществить==
и!=
тот путь, но это, как правило , не может быть очень эффективной реализации , я думаю. Было бы неплохо, если бы для всего этого не потребовались CRTP или другие уловки, но стандарт просто требовал бы автогенерации этих операторов, если бы они не были явно определены пользователем и<
определены.==
и!=
не может быть эффективно выражается с помощью ,<
что использование сравнения для всего общие. «Было бы хорошо , если бы не CRTP или другие приемов , не будет нужны» - возможно, но тогда CRTP может быть легко использован для создания множества других операторов (например , побитовые|
,&
,^
с|=
,&=
и^=
,+
-
*
/
%
от их форм присвоения, двоичный-
от одноместный отрицании и+
) - так много потенциально полезных вариаций этой темы, что простое предоставление языковой функции для одного довольно произвольного фрагмента не особенно элегантно.std::tie
для сравнения нескольких членов?Вам нужно явно определить
operator ==
дляMyStruct1
.Теперь сравнение == допустимо для двух таких объектов.
источник
Начиная с C ++ 20, должна быть возможность добавить в класс полный набор операторов сравнения по умолчанию (
==
,<=
и т. Д.), Объявив трехсторонний оператор сравнения по умолчанию ( оператор «космический корабль»), например:С совместимым компилятором C ++ 20 добавления этой строки в MyStruct1 и MyStruct2 может быть достаточно, чтобы позволить сравнения на равенство, при условии, что определение MyStruct2 совместимо.
источник
Сравнение не работает со структурами на C или C ++. Вместо этого сравнивайте по полям.
источник
По умолчанию у структур нет
==
оператора. Вам нужно будет написать свою собственную реализацию:источник
По умолчанию оператор == работает только с примитивами. Чтобы заставить ваш код работать, вам нужно перегрузить оператор == для вашей структуры.
источник
Потому что вы не написали оператор сравнения для своей структуры. Компилятор не генерирует его для вас, поэтому, если вы хотите сравнить, вы должны написать его самостоятельно.
источник