为什么';tc++;使用运算符==而不是运算符!=自动地 我知道C++不能自动定义一个类的代码>运算符==//>,但是为什么不能使用!(a==b)对于a!=b当操作员=不可用,但运算符==可用吗

为什么';tc++;使用运算符==而不是运算符!=自动地 我知道C++不能自动定义一个类的代码>运算符==//>,但是为什么不能使用!(a==b)对于a!=b当操作员=不可用,但运算符==可用吗,c++,C++,我知道std::rel_ops,尽管我今天之前没有听说过它。C++作为一种语言,不提供您没有明确要求的功能。我知道默认构造函数之类的东西有点违背了这一理念,但Stroustrup很早就做出了一个设计决策——你不用为你不用的东西付费。因此编译器不会自动生成您没有要求的内容 在1993年初,比亚恩的一封电子邮件中提到了这一点。如果我没记错的话,它也在D&E中;我手头没有它的副本可供参考。因为operator==并不一定意味着operator的反面= 我想不出任何一个操作符==不意味着的例子!接线员=

我知道std::rel_ops,尽管我今天之前没有听说过它。

C++作为一种语言,不提供您没有明确要求的功能。我知道默认构造函数之类的东西有点违背了这一理念,但Stroustrup很早就做出了一个设计决策——你不用为你不用的东西付费。因此编译器不会自动生成您没有要求的内容


在1993年初,比亚恩的一封电子邮件中提到了这一点。如果我没记错的话,它也在D&E中;我手头没有它的副本可供参考。

因为
operator==
并不一定意味着
operator的反面=

我想不出任何一个
操作符==
不意味着
的例子!接线员=,但它们是单独的运算符。C++最让人解放的时候,最令人沮丧的事情之一就是C++对如何编写代码的限制。如果您有一个实例,其中
操作符==
不是
操作符的对立面=,那么你应该能够在C++中表达。事实上,你可以

<>你在C++中使用好的和坏的。你可以认为这是在“坏”的集合中。

请记住,在绝大多数情况下,正确地实现
操作符是微不足道的=
运算符==
方面

bool Gizmo::operator!=(const Gizmo& rhs) const
{
  return !operator==(rhs);
}

语言不允许做你想做的事<代码>运算符==
运算符=是两个不同的运算符。我想不出一个例子,
!(x==y)
x=Y < /代码>会产生不同的结果,但请考虑<代码>操作符< /代码>。你为什么需要这两个?一个人可以写
xy)
,对吗?错

#include<iostream>

int main () {
   double y = 0.0;
   double x = y/y;

   std::cout << " (x <= y) -> " << (x <= y) << "\n";
   std::cout << "!(x >  y) -> " << !(x > y) << "\n";
}
#包括
int main(){
双y=0.0;
双x=y/y;
STD::CUT< P>第一个C++版本(AKA C++ 03在更正之后)引入了默认构造函数、复制构造函数、复制赋值操作符和析构函数的自动定义,以便能够在C++中编译C。
事实已经证明,这可能不是最好的选择,但是,许多为析构函数提供自定义定义的人忘记了定义复制构造函数和赋值运算符,结果弄得一团糟

隐式方法,比如隐藏的执行路径,似乎让开发人员感到困惑。我想我们都被咬了


然而,C++11对于按需默认方法有一个非常聪明的机制:

class Test { Test() = default; }; // a rather useless class...
因此,以C++03 constructors&co的自动生成为例,我不赞成引入这种自动生成,但肯定会支持:

bool operator!=(Test const&, Test const&) = default;
(显然,
运算符==
在范围内)

同样地:

bool operator>(Test const&, Test const&) = default;
bool operator<=(Test const&, Test const&) = default;
bool operator>=(Test const&, Test const&) = default;
通常可用于生成初始运算符:

template <typename T>
auto operator==(T const& left, T const& right) -> decltype(to_tuple(left), bool{}) {
    return to_tuple(left) == to_tuple(right);
}

template <typename T>
auto operator<(T const& left, T const& right) -> delctype(to_tuple(right), bool{}) {
    return to_tuple(left) < to_tuple(right);
}
然后:

class Test;

std::tuple<int, std::string const&> to_tuple(Test const&); // or boost::tuple

MY_DEFINE_TUPLE_EQUAL(Test);
MY_DEFINE_TUPLE_COMP(Test);
类测试;
std::tuple to_tuple(Test const&);//或boost::tuple
MY_DEFINE_TUPLE_EQUAL(测试);
MY_DEFINE_TUPLE_COMP(测试);

它与ADL一起工作,它围绕
到_tuple
生成内联代码(可能是内联的,也可能不是内联的),它生成正确且一致的
==
,因为它只适用于二进制逻辑,而不适用于三元逻辑:True、False、File-not-Found。因为
!=
不必与
==
相反。为什么编译器会猜到这一点并可能做出错误的决定?您甚至可以从
运算符==(即其返回类型不必是
bool
)你可以使用自动添加运算符,这些运算符可以从其他运算符推断到你的类中。我认为关闭此项不是建设性的,因为它似乎有点狂躁和哀怨。但如果你去掉狂躁,这是一个可以回答的合理问题。如果你可以将问题编辑为一个小mo,你可能会阻止关闭投票的浪潮re客观。正如你提到的,有例外。这些例外是最小的。有时我希望有更少的例外,但最低限度的意图肯定存在。IMO“你不为你不使用的东西付费”不适用于我请求/使用的!=并且成本可能为零。@XTF您请求了功能,但没有提供。结果本质上是一个查找错误。这不是例外情况之一。对于勇敢的人:
template bool operator!=(t const&rhs,t const&lhs){return!(rhs==lhs);}
我知道我不应该因为打字错误而编辑帖子,但“separate”应该是“separate”=自动使用= = =!如果!不可用,不阻止你定义!=它不是相反的= =,它?@ XTF:正确,但点是C++不愿意冒错误,如果你不知道,除非有好的理由。因为它是如此简单,定义自己的代码>运算符!= < /COD>,没有一个好的理由。n冒这个风险。其他语言如Haskell会做你想做的:。@Default:为拼写错误编辑帖子很好。我做了很多Tpyo,所以只要跟着我,你就会有很多机会。@MatthieuM.-me也是。我倾向于配置浮点环境,以便
NaN
Inf
引发浮点异常。我考虑了运算符<等,这个问题似乎更清楚。小编辑:右大括号在代码块之外。复制构造函数和赋值运算符的隐式生成一般来说是好的,除非定义了析构函数。并不是隐式生成让人困惑,只是不需要选择何时生成它们是的。不过,我希望编译器在这种情况下发出警告。@XTF:它们通常不会发出警告
#define MY_DEFINE_TUPLE_OPERATOR_IMPL(Type_, Op_)                       \
    inline bool operator Op_ (Type_ const& left, Type_ const& right) {  \
        return to_tuple(left) Op_ to_tuple(right);                      \
    }                                                                   \

#define MY_DEFINE_TUPLE_EQUAL(Type_)                                    \
    MY_DEFINE_TUPLE_OPERATOR_IMPL(Type_, ==)                            \
    MY_DEFINE_TUPLE_OPERATOR_IMPL(Type_, !=)

#define MY_DEFINE_TUPLE_COMP(Type_)                                     \
    MY_DEFINE_TUPLE_OPERATOR_IMPL(Type_,  <)                            \
    MY_DEFINE_TUPLE_OPERATOR_IMPL(Type_,  >)                            \
    MY_DEFINE_TUPLE_OPERATOR_IMPL(Type_, <=)                            \
    MY_DEFINE_TUPLE_OPERATOR_IMPL(Type_, >=)
class Test;

std::tuple<int, std::string const&> to_tuple(Test const&); // or boost::tuple

MY_DEFINE_TUPLE_EQUAL(Test);
MY_DEFINE_TUPLE_COMP(Test);