Меню

Оператор сравнения структур c



Операторы сравнения (справочник по C#) Comparison operators (C# reference)

Операторы сравнения (меньше чем), > (больше чем), (меньше или равно) и >= (больше или равно) (или реляционные операторы) сравнивают операнды. The (less than), > (greater than), (less than or equal), and >= (greater than or equal) comparison, also known as relational, operators compare their operands. Эти операторы поддерживаются всеми целочисленными типами и типами с плавающей запятой. Those operators are supported by all integral and floating-point numeric types.

Если какой-то из операндов операторов == , , > , и >= не является числом (Double.NaN или Single.NaN), результатом операции будет false . For the == , , > , , and >= operators, if any of the operands is not a number (Double.NaN or Single.NaN), the result of operation is false . Это означает, что значение NaN не больше, не меньше и не равно любому другому значению double (или float ), включая NaN . That means that the NaN value is neither greater than, less than, nor equal to any other double (or float ) value, including NaN . Дополнительные сведения и примеры см. в справочных статьях по Double.NaN или Single.NaN. For more information and examples, see the Double.NaN or Single.NaN reference article.

Тип char также поддерживает операторы сравнения. The char type also supports comparison operators. В случае операндов char сравниваются соответствующие коды символов. In the case of char operands, the corresponding character codes are compared.

Типы перечисления также поддерживают операторы сравнения. Enumeration types also support comparison operators. Если операнды имеют одинаковый тип enum, сравниваются соответствующие значения базового целочисленного типа. For operands of the same enum type, the corresponding values of the underlying integral type are compared.

Операторы == и != проверяют равенство или неравенство своих операндов. The == and != operators check if their operands are equal or not.

Оператор «меньше чем» Less than operator

Оператор возвращает true , если его левый операнд меньше правого. В противном случае возвращается false : The operator returns true if its left-hand operand is less than its right-hand operand, false otherwise:

Оператор «больше чем» > Greater than operator >

Оператор > возвращает true , если его левый операнд больше правого. В противном случае возвращается false : The > operator returns true if its left-hand operand is greater than its right-hand operand, false otherwise:

Оператор «меньше или равно» Less than or equal operator

Оператор возвращает true , если его левый операнд меньше правого или равен ему. В противном случае возвращается false : The operator returns true if its left-hand operand is less than or equal to its right-hand operand, false otherwise:

Оператор «больше или равно» >= Greater than or equal operator >=

Оператор >= возвращает true , если его левый операнд больше правого или равен ему. В противном случае возвращается false : The >= operator returns true if its left-hand operand is greater than or equal to its right-hand operand, false otherwise:

Возможность перегрузки оператора Operator overloadability

Определяемый пользователем тип может перегружать операторы , > , и >= . A user-defined type can overload the , > , , and >= operators.

Если тип перегружает один из операторов и > , он должен также перегружать операторы и > . If a type overloads one of the or > operators, it must overload both and > . Если тип перегружает один из операторов и >= , он должен также перегружать операторы и >= . If a type overloads one of the or >= operators, it must overload both and >= .

Источник

Перегрузка оператора сравнения для структуры, симметрично сравнивая мою структуру с типом int?

Я пытаюсь перегрузить эти операторы:
, , == , >= , > а может и позже != ,
в структуре.

Кажется, что сравнение объекта структуры с другим объект той же структуры это просто, потому что при перегрузке оператора для этого сценария определение автоматически становится симметричным.

Но что, если я хочу сравнить мою структуру FOOD для int ?
Это также легко, пока FOOD приходит первым, тем не мение, а как насчет сценария, когда int приходит первым? Как мне определить, что без g ++, выдающего мне столько ошибок «должен содержать ровно один аргумент»?

имеет проблемы из-за «более чем одного аргумента». Я понимаю.

На всех форумах, которые я ищу по сетям, похоже, что все используют решение friend Но их трудности всегда в контексте классов, а не структур. Как это делается для s struct?

g++ дает мне эти ошибки:

Решение

Определите это вне FOOD структура:

Не забудьте удалить это неправильное объявление из FOOD структура:

и соответствующее определение:

Повторите то же самое для других операторов.

Решение

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

Читайте также:  Сравнение процессоров socket am3

Другие решения

Этот тип оператора

не может быть членом Функция-член принимает один дополнительный, неявный параметр типа FOOD* (возможно, квалифицированное cv), поэтому приведенный выше пример на самом деле принимает три аргумента. Вы должны сделать его не членом.

Я думаю, что самым простым подходом было бы дать вашему классу явный int оператор преобразования

Также обратите внимание, что все операторы сравнения могут быть выражены в виде одного, например bool operator (этот метод используется, например, в ассоциативных контейнерах библиотеки std)

Источник

Как сравнивать структуры

Есть структура например

Возможно ли сравнивать структуры?
Здравствуйте, возможно ли сравнивать структуры? #include typedef char str; struct inf<.

Как сравнивать char ‘\’?
Компиляция следуещего кода приводит к ошибке: if(field == field && field == ‘\’) turnOn = true;.

Как сравнивать 2 текста?
У меня есть 2 текстовых файлов.В етих файлах одиноковые слова, только в одном ети слова начинаютса.

как сравнивать даты?
Имеется текстовый файл, в нем список учебных дней когда есть математика, в формате.

Добавлено через 45 минут
//Напишу попроще без перегрузки

Объявил нормально но неправильно сравнил

Как ни верти, а придется сравнивать отдельно каждый элемент. Компилятор С++ не генерирует неявных операторов сравнения для классов. Сравнение можно (нужно) завернуть в оператор (см. ответ Shamsik), но писать такой оператор все равно придется самому.

Можно отказаться от использования своего типа и перейти на std::pair

(или на std::tuple ). Тогда оператор сравнения вам будет предоставлен готовый. Но имена полей в TIME получатся не такие говорящие, как они были у вас: first and second в случае std::pair .

Выбирайте, что вам больше нравится.

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Как сравнивать ip-адреса (+)
Всем привет! В общем задача у меня стоит такая: есть список диапазонов ip-адресов, напрмер.

Подскажите как сравнивать
Подскажите как сравнивать между собой введенные значения.(в структурах)

Как сравнивать строки?
Что-то смотрю в туториалы, но ничего не выходит. Как написать сравнение строк.

Как сравнивать строки?
Ребят, а может вы знаете, как в этом языке сравнивать строки? походу просто string1>string2 не.

Источник

Автоматическая генерация операторов сравнения структур в C++

Язык C++ для всех пользовательских классов и структур генерирует по умолчанию копирующий конструктор и копирующий оператор присваивания. Тем самым для важного ряда случаев программист освобождается от написания указанных функций вручную. Например, операторы по умолчанию хорошо работают для структур, которые содержат данные. При этом данные могут храниться как в простых типах, так и в сложных контейнерах, таких как std::vector или std::string.

В свете этого удобно было бы иметь и операторы сравнения структур == и != по умолчанию, однако компилятор C++, в соответствии со стандартом, не генерирует их.

Написать оператор почленного сравнения структур несложно, однако такая организация программы является неудобной и опасной с точки зрения ошибок. Скажем, если программист добавит новый член в структуру, но забудет добавить соответствующее сравнение в пользовательском операторе сравнения — то в программе образуется довольно трудно диагностируемая ошибка. Тем более что объявление структуры и пользовательский оператор ее сравнения обычно разнесены друг от друга, так как находятся в разных файлах (*.h и *.cpp).

Автоматизировать написание операторов почленного сравнения в рамках C++ непросто, так как в этом языке отсутствуют средства, позволяющие во время работы программы выяснить, сколько и каких членов содержится в структуре.

В середине 2000х годов, работая над крупным проектом, который постоянно эволюционировал и требовал частых изменений структур данных, я задался целью решить вопрос операторов сравнения раз и навсегда. В результате была создана конструкция на C++ с применением макросов, позволяющая объявлять структуры с последующей автоматической генерацией операторов почленного сравнения их. Эта же конструкция позволила автоматически реализовать и другие почленные операции: загрузка и сохранение данных в файлы. Предлагаю ее вашему вниманию.

Другие существующие решения
Решение на базе макросов
Пример использования

Пусть нам нужно создать структуру для хранения данных о людях, эквивалентную следующей обычной структуре:

На базе моей библиотеки структура с автоматическими почленными операциями объявляется так:

После этого, один раз на всю программу, необходимо скомпилировать следующий вызов макроса в одном из *.cpp-файлов:

Всё! Теперь можно спокойно пользоваться данными структурами как обычно, и сравнивать их на равенство или неравенство, не заботясь о написании соответствующих операторов. Например:

Реализация

Как видно из приведенного выше, в начале определения каждой структуры необходимо вызвать макрос PARAMSTRUCT_DECLARE_BEGIN(x), который определит для этой структуры некоторые общие типы и статические служебные члены. После этого нужно при объявлении каждого пользовательского члена вызывать второй макрос, DECLARE_MEMBER_PARAMSTRUCT(type, name), который, помимо объявления собственно члена с указанным именем, определяет служебные члены структуры, связанные с ним.

Основные идеи реализации:

  • Для каждого члена структуры автоматически генерируется функция сравнения этого члена.
  • Указатели на функции сравнения хранятся в статическом массиве. Оператор сравнения просто перебирает все элементы этого массива и вызывает функцию сравнения для каждого члена.
  • При старте программы происходит инициализация этого массива так, чтобы не дублировать код по объявлению членов структуры.
Читайте также:  Рейтинг банков россии сравни

1. Автогенерация функций сравнения каждого члена

Каждая такая функция является членом структуры и производит сравнение «своего» члена данных. Она генерируется в макросе DECLARE_MEMBER_PARAMSTRUCT(type, name) следующим образом:

Где ThisParamFieldClass – это тип нашей структуры, который объявляется через typedef в головном макросе — см. ниже.

2. Массив с указателями на функции сравнения

Головной макрос PARAMSTRUCT_DECLARE_BEGIN(x) объявляет статический массив, в котором хранятся указатели на каждую из функций сравнения членов. Для этого сначала определяется их тип:

А затем объявляется массив:

Здесь же объявляются операторы сравнения:

Реализуется оператор сравнения другим макросом (PARAMFIELD_IMPL), однако его реализация является тривиальной при наличии заполненного массива stat_data: нужно всего лишь вызвать функцию сравнения для каждого элемента этого массива.
Для одного лишь сравнения структур нет необходимости хранить в массиве имена членов структуры. Однако хранение имен позволяет расширять концепцию, применяя ее не только к почленному сравнению, но и к другим операциям, например, сохранению и загрузке в текстовом формате, пригодном для чтения человеком.

3. Заполнение данных о членах структуры

Остается решить вопрос с заполнением массива stat_data. Поскольку информация о членах изначально недоступна нигде, кроме макроса DECLARE_MEMBER_PARAMSTRUCT, то заполнять массив возможно только оттуда (прямо или косвенно). Однако этот макрос вызывается внутри объявления структуры, что не самое удобное место для инициализации std::vector. Я решил эту проблему с помощью служебных объектов. Для каждого члена структуры объявляется служебный класс и объект этого класса. Этот класс имеет конструктор — он и добавляет информацию об элементе в статический массив stat_data:

где populate_statdata – статический флаг, который объявляется в головном макросе и сигнализирует о том, следует ли заполнять массив stat_data именами членов структуры и функциями их сравнения. При старте программы механизм инициализации, описанный ниже, устанавливает populate_statdata=true и создает один экземпляр структуры. При этом конструкторы служебных объектов, связанные с каждым членом структуры, заполняют массив данными о членах. После этого устанавливается populate_statdata=false, и статический массив с информацией о членах больше не изменяется. Данное решение приводит к некоторым потерям времени при каждом создании структуры пользовательской программой, на проверку флага populate_statdata. Однако расход памяти не увеличивается: служебный объект не содержит членов данных, только конструктор.

И наконец, механизм управления флагом populate_statdata: реализуется с помощью статического служебного объекта с конструктором, одного на всю структуру. Этот объект объявляется в головном макросе:

Реализация конструктора находится в макросе PARAMFIELD_IMPL(x):

Источник

Перегрузка операторов в C++. Способы применения

Перегрузка операторов в C++. Способы применения

В прошлой части мы рассмотрели основные аспекты использования перегрузки операторов. В этом материалы вашему вниманию будут представлены перегружаемые операторы C++. Для каждого раздела характерна семантика, т.е. ожидаемое поведение. Кроме того, будут показаны типичные способы объявления и реализации операторов.

В примерах кода X означает пользовательский тип, для которого реализован оператор. T — это необязательный тип, пользовательский либо встроенный. Параметры бинарного оператора будут называться lhs и rhs . Если оператор будет объявлен как метод класса, у его объявления будет префикс X:: .

operator=

  • Определение справа налево: в отличие от большинства операторов, operator= правоассоциативен, т.е. a = b = c означает a = (b = c) .

Копирование

  • Семантика: присваивание a = b . Значение или состояние b передаётся a . Кроме того, возвращается ссылка на a . Это позволяет создавать цепочки вида c = a = b .
  • Типичное объявление: X& X::operator= (X const& rhs) . Возможны другие типы аргументов, но используется это нечасто.
  • Типичная реализация:

Перемещение (начиная с C++11)

  • Семантика: присваивание a = temporary() . Значение или состояние правой величины присваивается a путём перемещения содержимого. Возвращается ссылка на a .
  • Типичные объявление и реализация:
  • Сгенерированный компилятором operator= : компилятор может создать только два вида этого оператора. Если же оператор не объявлен в классе, компилятор пытается создать публичные операторы копирования и перемещения. Начиная с C++11 компилятор может создавать оператор по умолчанию:

Сгенерированный оператор просто копирует/перемещает указанный элемент, если такая операция разрешена.

operator+, -, *, /, %

  • Семантика: операции сложения, вычитания, умножения, деления, деления с остатком. Возвращается новый объект с результирующим значением.
  • Типичные объявление и реализация:

Обычно, если существует operator+ , имеет смысл также перегрузить и operator+= для того, чтобы использовать запись a += b вместо a = a + b . Если же operator+= не перегружен, реализация будет выглядеть примерно так:

Унарные operator+, —

  • Семантика: положительный или отрицательный знак. operator+ обычно ничего не делает и поэтому почти не используется. operator- возвращает аргумент с противоположным знаком.
  • Типичные объявление и реализация:

operator >

  • Семантика: во встроенных типах операторы используются для битового сдвига левого аргумента. Перегрузка этих операторов с именно такой семантикой встречается редко, на ум приходит лишь std::bitset . Однако, для работы с потоками была введена новая семантика, и перегрузка операторов ввода/вывода весьма распространена.
  • Типичные объявление и реализация: поскольку в стандартные классы iostream добавлять методы нельзя, операторы сдвига для определённых вами классов нужно перегружать в виде свободных функций:
Читайте также:  Как русскую культуру сравнить с волшебной горой

Кроме того, тип левого операнда может быть любым классом, которые должен вести себя как объект ввода/вывода, то есть правый операнд может быть и встроенного типа.

Бинарные operator&, |, ^

  • Семантика: Битовые операции «и», «или», «исключающее или». Эти операторы перегружаются очень редко. Опять же, единственным примером является std::bitset .

operator+=, -=, *=, /=, %=

  • Семантика: a += b обычно означает то же, что и a = a + b . Поведение остальных операторов аналогично.
  • Типичные определение и реализация: поскольку операция изменяет левый операнд, скрытое приведение типов нежелательно. Поэтому эти операторы должны быть перегружены как методы класса.

operator&=, |=, ^=, >=

  • Семантика: аналогична operator+= , но для логических операций. Эти операторы перегружаются так же редко, как и operator| и т.д. operator и operator>>= не используются для операций ввода/вывода, поскольку operator и operator>> уже изменяют левый аргумент.

operator==, !=

  • Семантика: проверка на равенство/неравенство. Смысл равенства очень сильно зависит от класса. В любом случае, учитывайте следующие свойства равенств:
    1. Рефлексивность, т.е. a == a .
    2. Симметричность, т.е. если a == b , то b == a .
    3. Транзитивность, т.е. если a == b и b == c , то a == c .
  • Типичные объявление и реализация:

Вторая реализация operator!= позволяет избежать повторов кода и исключает любую возможную неопределённость в отношении любых двух объектов.

operator , >=

  • Семантика: проверка на соотношение (больше, меньше и т.д.). Обычно используется, если порядок элементов однозначно определён, то есть сложные объекты с несколькими характеристиками сравнивать бессмысленно.
  • Типичные объявление и реализация:

Реализация operator> с использованием operator или наоборот обеспечивает однозначное определение. operator может быть реализован по-разному, в зависимости от ситуации. В частности, при отношении строго порядка operator== можно реализовать лишь через operator :

operator++, –

  • Семантика: a++ (постинкремент) увеличивает значение на 1 и возвращает старое значение. ++a (преинкремент) возвращает новое значение. С декрементом operator— все аналогично.
  • Типичные объявление и реализация:

operator()

  • Семантика: исполнение объекта-функции (функтора). Обычно используется не для изменения объекта, а для использования его в качестве функции.
  • Нет ограничений на параметры: в отличие от прошлых операторов, в этом случае нет никаких ограничений на количество и тип параметров. Оператор может быть перегружен только как метод класса.
  • Пример объявления:

operator[]

  • Семантика: доступ к элементам массива или контейнера, например, в std::vector , std::map , std::array .
  • Объявление: тип параметра может быть любым. Тип возвращаемого значения обычно является ссылкой на то, что хранится в контейнере. Часто оператор перегружается в двух версиях, константной и неконстантной:

operator!

  • Семантика: отрицание в логическом смысле.
  • Типичные объявление и реализация:

explicit operator bool

  • Семантика: использования в логическом контексте. Чаще всего используется с умными указателями.
  • Реализация:

operator&&, ||

  • Семантика: логические «и», «или». Эти операторы определены только для встроенного логического типа и работают по «ленивому» принципу, то есть второй аргумент рассматривается, только если первый не определяет результат. При перегрузке это свойство теряется, поэтому перегружают эти операторы редко.

Унарный operator*

  • Семантика: разыменовывание указателя. Обычно перегружается для классов с умными указателями и итераторами. Возвращает ссылку на то, куда указывает объект.
  • Типичные объявление и реализация:

operator->

  • Семантика: доступ к полю по указателю. Как и предыдущий, этот оператор перегружается для использования с умными указателями и итераторами. Если в коде встречается оператор -> , компилятор перенаправляет вызовы на operator-> , если возвращается результат пользовательского типа.
  • Usual implementation:

operator->*

  • Семантика: доступ к указателю-на-поле по указателю. Оператор берёт указатель на поле и применяет его к тому, на что указывает *this , то есть objPtr->*memPtr — это то же самое, что и (*objPtr).*memPtr . Используется очень редко.
  • Возможная реализация:

Здесь X — это умный указатель, V — тип, на который указывает X , а T — тип, на который указывает указатель-на-поле. Неудивительно, что этот оператор редко перегружают.

Унарный operator&

  • Семантика: адресный оператор. Этот оператор перегружают очень редко.

operator,

  • Семантика: встроенный оператор «запятая», применённый к двум выражениям, выполняет их оба в порядке записи и возвращает значение второго из них. Перегружать его не рекомендуется.

operator

  • Семантика: оператор побитовой инверсии. Один из наиболее редко используемых операторов.

Операторы приведения типов

  • Семантика: позволяет скрытое или явное приведение объектов класса к другим типам.
  • Объявление:

Эти объявления выглядят странно, поскольку в них отсутствует тип возвращаемого значения. Он является частью имени оператора у не указывается дважды. Стоит помнить, что большое количество скрытых приведений может повлечь за собой непредвиденные ошибки в работе программы.

operator new, new[], delete, delete[]

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

Заключение

Основной мыслью является следующее: не стоит перегружать операторы только потому, что вы умеете это делать. Перегружайте их лишь в тех случаях, когда это выглядит естественным и необходимым. Но помните, что если вы перегрузите один оператор, то придётся перегружать и другие.

Источник