Могу ли я использовать оператор == если я только реализовал оператор
я реализовал operator<
для определенного объекта.
Логично, если !(a < b)
и !(b < a)
значит a == b
.
это выводится автоматически? Могу ли я использовать ==
если я только осуществить <
?
13 ответов:
C++ не может сделать это автоматически по нескольким причинам:
- не имеет смысла сравнивать каждый тип с
operator<
, поэтому тип может не обязательно определять aoperator<
.
- это означает, что
operator==
не может быть автоматически определен в терминахoperator<
operator<
не требуется сравнивать свои аргументы. Программист может определить операторы для их типов, чтобы сделать почти все что угодно в своих рассуждениях.
- это означает, что ваше высказывание о
!(a < b) && !(b < a)
, эквивалентнойa == b
может быть не обязательно верно, если эти операторы определены.
если вы хотите
operator==
функция для ваших типов, просто определите один самостоятельно. Это не так уж и сложно:)// For comparing, something like this is used bool operator==(const MyType& lhs, const MyType& rhs) { // compare (or do other things!) however you want } // ... though it's not the only thing you can do // - The return type can be customised // - ... as can both of the arguments const MyType& operator==(int* lhs, const MyType* const rhs) { return lhs; }
он не может сделать вывод
==
С<
потому что не все типы заказал, какstd::complex
. Это2 + 3i > 1 + 4i
или нет?более того, даже в типах, которые обычно упорядочены, вы все равно не можете вывести равенство из
>
или<
, например IEEE-754 NaNdouble n = std::numeric_limits<double>::quiet_NaN(); std::cout << "NaN == NaN: " << (n == n) << '\n'; std::cout << "NaN < NaN: " << (n < n) << '\n'; std::cout << "NaN > NaN: " << (n > n) << '\n'; std::cout << "NaN != NaN: " << (n != n) << '\n';
они все вернут false, кроме последнего
нет. Этот метод хорошо работает на числовых объектах, которые называются полностью упорядоченном. Для всех видов набора / класса никто не может гарантировать это отношение. Даже никто не может гарантировать
operator <
сравнил бы что-то.так
==
это не что иное, как==
. Вы можете реализовать==
by<
но это не работает для всех, и стандарты C++ не сделают этого для вас.
логически, если !(a
чтобы выразить то, что другие заявили в математических терминах: предполагая, что у вас есть
operator <
возвращаетbool
и определена строгий слабый порядок, а вы реализуетеoperator ==
в качестве возврата!(a < b) && !(b < a)
, то этот оператор определяет отношение эквивалентности в соответствии с данной строгий порядок. Однако C++ не требуетoperator <
чтобы определить строгий слабый порядок, ниoperator ==
для определения отношения эквивалентности (хотя многие стандартные алгоритмы, такие какsort
может неявно использовать эти операторы и требовать строгого слабого порядка rsp. отношение эквивалентности.)если вы хотите определить все остальные операторы отношений на основе и в соответствии с вашим
operator <
строгий слабый порядок, повышение.Операторы могут сэкономить вам немного набрав.потому что это так легко неправомерное использование
operator <
Это не соответствует требованиям стандартного алгоритма, например, случайно используя его черезstd::sort
,std::lower_bound
etc., Рекомендую определитьoperator <
либо как строгий слабый порядок, либо вообще нет. Пример CodesInChaos дал частичный порядок, который не отвечает требованию "транзитивности несопоставимости" строгого слабого порядка. Поэтому я бы рекомендовал называть такое отношение другим именем, напримерbool setLess(const MySet &, const MySet &)
.источники:
C++ не выводит это автоматически. Ибо
operator>
,operator<=
иoperator>=
, вы могли бы использоватьstd::rel_ops
; для этого требуется толькоoperator<
. Однако это не обеспечиваетoperator==
С точки зренияoperator<
. Вы можете сделать это сами вот так:template <class T> bool operator==(T const& lhs, T const& rhs) { return !((lhs < rhs) or (rhs < lhs)); }
внимание:
!((lhs < rhs) or (rhs < lhs))
и!(lhs < rhs) and !(rhs < lhs)
эквивалентны, математически.
компилятор не выводит
==
С<
.вы можете проверить это с помощью простого примера:
#include <iostream> struct A { A(int r):i{r}{} int i; }; bool operator<(A const & a1, A const& a2) { return a1.i < a2.i; } int main(int argc, char* argv[]) { A a1{2}; A a2{3}; if(a1 == a2) { std::cout << "equals\n"; } return 0; }
GCC
дает вам эту ошибку:main.cpp:20:11: error: no match for 'operator==' (operand types are 'A' and 'A') if(a1 == a2) {
как многие заявили, Нет вы не можете, и нет компилятор не должен.
это не значит, что это не должно быть легко из
<
до==
и все огромное множество.boost:: operators пытается сделать это легко. Используйте его и готово.
если вы хотите сделать это самостоятельно, это также займет всего лишь немного кода, чтобы переопределить то, что boost предоставляет вам:
namespace utility { namespace details { template<class...>using void_t=void; template<template<class...>class Z, class, class...Ts> struct can_apply:std::false_type{}; template<template<class...>class Z, class...Ts> struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:std::true_type{}; } template<template<class...>class Z, class...Ts> using can_apply = ::utility::details::can_apply<Z,void,Ts...>; } namespace auto_operators { template<class T, class U> using less_r = decltype( std::declval<T const&>() < std::declval<U const&>() ); template<class T, class U> using can_less = ::utility::can_apply<less_r, T, U>; struct order_from_less { template<class T, class U> using enabled = std::enable_if_t< std::is_base_of<order_from_less, T>{} && std::is_base_of<order_from_less, U>{} && can_less<T, U>{}, bool >; template<class T, class U> friend enabled<U,T> operator>(T const& lhs, U const& rhs) { return rhs < lhs; } template<class T, class U> friend enabled<U,T> operator<=(T const& lhs, U const& rhs) { return !(lhs > rhs); } template<class T, class U> friend enabled<T,U> operator>=(T const& lhs, U const& rhs) { return !(lhs < rhs); } }; struct equal_from_less:order_from_less { template<class T, class U> using enabled = std::enable_if_t< std::is_base_of<order_from_less, T>{} && std::is_base_of<order_from_less, U>{} && can_less<T, U>{} && can_less<U,T>{}, bool >; template<class T, class U> friend enabled<U,T> operator==(T const& lhs, U const& rhs) { return !(lhs < rhs) && !(rhs < lhs); } template<class T, class U> friend enabled<U,T> operator!=(T const& lhs, U const& rhs) { return !(lhs==rhs); } }; }
выше только написано один раз, или эквивалент cose получил от
#include
импульс.как только у вас есть boost, или выше, это так же просто, как что-то вроде:
struct foo : auto_operators::equal_from_less { int x; foo( int in ):x(in) {} friend bool operator<( foo const& lhs, foo const& rhs ) { return lhs.x < rhs.x; } };
и
foo
теперь на нем определены все операторы упорядочения и сравнения.int main() { foo one{1}, two{2}; std::cout << (one < two) << "\n"; std::cout << (one > two) << "\n"; std::cout << (one == two) << "\n"; std::cout << (one != two) << "\n"; std::cout << (one <= two) << "\n"; std::cout << (one >= two) << "\n"; std::cout << (one == one) << "\n"; std::cout << (one != one) << "\n"; std::cout << (one <= one) << "\n"; std::cout << (one >= one) << "\n"; }
видео.
суть всего этого в том, что C++ не предполагает, как язык, что
<
означает>
и>=
и==
все имеет смысл. Но вы можете написать библиотека, которая позволяет взять типа<
определено,и добавление тривиального базового класса внезапно делает все эти другие операции, определенные с нулевой стоимостью выполнения.
есть шаблоны, определенные в
std::rel_ops
пространство имен, которые автоматически определяют отсутствующие операторы.он не определяет оператор равенства на основе оператора less, как вы хотите.
тем не менее это весьма полезно; если вы определяете оператор less и оператор равенства, у вас будут другие операторы сравнения бесплатно.
ответ-Нет, вам просто нужен простой тест
struct MyType{ int value; }; bool operator < (MyType& a, MyType& b) { return a.value < b.value; } int main(int argc, char* argv[]) { MyType a = {3}; MyType b = {4}; if (a == b) std::cout << "a==b" << std::endl; if (a < b) std::cout << "a < b" << std::endl; }
g++ 4.8.2 жалуется:
main.cpp: в функции ' int main(int, char**)':
main.cpp: 16: 11: error: нет соответствия для ' operator== '(типы операндов - ‘MyType’ и ‘MyType’)
но есть что-то подобное, что работает в C++, проверить это концепции c++: сравнить
Он говорит:
equiv (a, b), выражение эквивалентно !comp(a, b)&&!comp (b, a)
В дополнение к другим ответы,
компилятор не может даже вывести
!=
С==
struct MyType { int value; }; bool operator == (const MyType& a, const MyType& b) { return a.value == b.value; } int main() { MyType a = {3}; MyType b = {4}; if (a != b) // (* compilation Error *) std::cout << "a does not equal b" << std::endl; }
было бы неплохо, если бы была возможность сообщить компилятору, что остальные операторы rational применяются к вашему классу.
есть, как объясняется в некоторых ответах в
<utility>
заголовок-то, что может обеспечить такую функциональность. вам нужно будет добавить следующую строку в началеmain
:using namespace std::rel_ops;
однако использование этого подхода является дорогостоящим и приведет к перегрузке неоднозначности во всем месте, как отметил JDługosz.
рассмотрим следующий пример:
class point{ unsigned int x; unsigned int y; public: bool operator <(const point& other){ return (x+y) < (other.x+other.y); } bool operator == (const point& other){ return (x==other.x) && (y==other.y); } }
и тогда у нас есть:
point a{1, 2}; point b{2, 1};
!(a
вид.
Но вам понадобится boost:: operatorsперегруженные операторы для типов классов обычно встречаются в группах. Если вы можно написать x + y, вы, вероятно, также хотите иметь возможность писать x += y. если вы можете написать x y, x > = y и x = y !(x ускорение/операторов.ГЭС справка по шаблонам создавая операторы для вас в области пространства имен на основе других операторы, которые вы определили в своем классе.
ответ ясен нет. Нет никакого скрытого способа. Классы C++ позволяют перегружать операторы. Итак, ваша идея, что логически,
if !(a < b) and !(b < a)
значитa == b
. правильно. И, вы можете перегрузить операторов, как показано ниже. Например, класс дроби:class Fraction { int num; int denom; . . . public: . . . bool operator < (const Fraction &other) { if ((this->num * other.denom) < (this->denom * other.num)) return false; else return true; } bool operator == (const Fraction &other) ( if (!(*this < other) && !(other < *this)) { return true; else return false; } };