Могу ли я использовать оператор == если я только реализовал оператор


я реализовал operator< для определенного объекта. Логично, если !(a < b) и !(b < a) значит a == b.

это выводится автоматически? Могу ли я использовать == если я только осуществить <?

13 51

13 ответов:

C++ не может сделать это автоматически по нескольким причинам:

  1. не имеет смысла сравнивать каждый тип с operator<, поэтому тип может не обязательно определять a operator<.
    • это означает, что operator== не может быть автоматически определен в терминах operator<
  2. 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 NaN

double 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;
       }
};