[英]C++ greater than or equal to operator
In C++, for the operator greater than or equal to (">="), is it enough to have the operators equal ("=") and greater (">") overloaded to have functionality for the greater than or equal to (">=")? 在C ++中,对于大于或等于(“> =”)的运算符,是否足以让运算符等于(“=”)和更大(“>”)重载以具有大于或等于的功能( “> =”)? Or do I need to overload the operator (">=") to have functionality for it?
或者我是否需要重载运算符(“> =”)以使其具有功能?
is it enough to have the operators equal ("=")
是否足以使运算符相等(“=”)
Equal operator in c++ is ==
c ++中的等于运算符是
==
OR do I need to overload the operator (">=") to have functionality for it?
或者我需要重载运算符(“> =”)以使其具有功能吗?
It depends what you mean by functionality. 这取决于你的功能。 If you mean that if you define
operator==
and operator>
will compiler generate operator>=
automagically for you? 如果你的意思是,如果你定义
operator==
和operator>
编译器会为你自动生成operator>=
吗? No, it would not, you have to implement it using existing operators or not. 不,它不会,你必须使用现有的运营商来实现它。
operator >=
is not a combination of operator >
and operator =
. operator >=
不是operator >
和operator =
的组合。 operator >=
is its own operator but you can implement it in terms of operator <
Typically you would have something like operator >=
是它自己的运算符,但你可以用operator <
实现它。通常你会有类似的东西
inline bool operator==(const X& lhs, const X& rhs){ /* do actual comparison */ } inline bool operator!=(const X& lhs, const X& rhs){return !operator==(lhs,rhs);} inline bool operator< (const X& lhs, const X& rhs){ /* do actual comparison */ } inline bool operator> (const X& lhs, const X& rhs){return operator< (rhs,lhs);} inline bool operator<=(const X& lhs, const X& rhs){return !operator> (lhs,rhs);} inline bool operator>=(const X& lhs, const X& rhs){return !operator< (lhs,rhs);}
From sbi's answer on What are the basic rules and idioms for operator overloading? 来自sbi的回答有关运算符重载的基本规则和习惯用法是什么?
No, C++ does not write those operators for you. 不,C ++不会为您编写这些运算符。
If you think that sucks, you are right. 如果你认为这很糟糕,那你就是对的。 A bunch of ways to make this suck less have been done.
已经完成了许多减少这种麻烦的方法。 I'll talk about 4 of them.
我会谈谈他们中的4个。
In c++20 , if you write operator<=>
(the 3-way "spaceship" operator) properly, or =default
it, then all of <
, <=
, >=
, >
, !=
and ==
will be written for you. 在c ++ 20中 ,如果正确地编写
operator<=>
( 3向 “太空飞船”运算符),或者=default
运算符,那么<
, <=
, >=
, >
, !=
和==
都将是写给你的。
struct bob {
int x,y;
auto operator<=>( bob const& )const = default;
};
The above bob
has every <
==
etc operator written for it by C++ now. 上面的
bob
现在有C ++为它编写的每个<
==
etc运算符。
Prior to c++20 you have to write all of them if you want all of them. 在c ++ 20之前,如果你想要所有这些,你必须编写所有这些。 This is tedious and error-prone.
这很乏味且容易出错。
Using std::tie
and invoking <
and the like on them is slightly less error-prone: 使用
std::tie
并在它们上调用<
等等稍微不易出错:
struct bob {
int x, y;
friend bool operator<( bob const& lhs, bob const& rhs ) {
return std::tie(lhs.x, lhs.y) < std::tie(rhs.x, rhs.y);
}
};
or even 甚至
struct bob {
int x, y;
friend auto as_tie( bob const& b ) { // C++14
return std::tie(b.x, b.y);
}
friend bool operator<( bob const& lhs, bob const& rhs ) {
return as_tie(lhs) < as_tie(rhs);
}
};
because tuple
does a proper lexographic comparison; 因为
tuple
了适当的词汇比较; writing lexographic comparions without bugs is annoying. 写没有错误的词汇比较令人讨厌。
When comparing strings you usually use strcmp
. 比较字符串时,通常使用
strcmp
。 This returns a negative number if less, a positive number if greater, and 0 if equal. 如果更小则返回负数,如果更大则返回正数,如果相等则返回0。 This pattern can be more efficient than doing
<
or ==
repeatedly. 这种模式比重复执行
<
或==
更有效。
Making a single strcmp
like function produce <
==
and the other comparison operations can be done: 制作单个
strcmp
函数会产生<
==
并且可以完成其他比较操作:
namespace utils {
template<class D>
struct use_cmp {
friend bool operator<( use_cmp<D> const& lhs, use_cmp<D> const& rhs ) {
return cmp( lhs.self(), rhs.self() ) < 0;
}
friend bool operator>( use_cmp<D> const& lhs, use_cmp<D> const& rhs ) {
return cmp( lhs.self(), rhs.self() ) > 0;
}
friend bool operator<=( use_cmp<D> const& lhs, use_cmp<D> const& rhs ) {
return cmp( lhs.self(), rhs.self() ) <= 0;
}
friend bool operator>=( use_cmp<D> const& lhs, use_cmp<D> const& rhs ) {
return cmp( lhs.self(), rhs.self() ) >= 0;
}
friend bool operator==( use_cmp<D> const& lhs, use_cmp<D> const& rhs ) {
return cmp( lhs.self(), rhs.self() ) == 0;
}
friend bool operator!=( use_cmp<D> const& lhs, use_cmp<D> const& rhs ) {
return cmp( lhs.self(), rhs.self() ) != 0;
}
private:
D const& self() const { return *static_cast<D const*>(this); }
};
}
Now supose we have a type: 现在我们有一个类型:
struct bob {
int x, y;
};
and we want to be able to use comparison operators on it: 我们希望能够在其上使用比较运算符:
struct bob : utils::use_cmp<bob>
{
int x, y;
bob( int x_, int y_ ):x(x_), y(y_) {} // constructor
friend int cmp( bob const& lhs, bob const& rhs ) {
if (lhs.x < rhs.x) return -1;
if (lhs.x > rhs.x) return 1;
if (lhs.y < rhs.y) return -1;
if (lhs.y > rhs.y) return 1;
return 0;
}
};
and using the magic of CRTP bob
now has every comparison operator written for it. 并且使用CRTP
bob
的魔力现在已经为它编写了每个比较运算符。
Live example . 实例 。
That annoying friend int cmp
(which gets more annoying the more members you have in it) can be handled by yet more boilerplate helper code: 那个讨厌的
friend int cmp
(它让你的成员越多越烦恼)可以通过更多的样板助手代码来处理:
namespace utils {
template<class...Ts>
int cmp( std::tuple<Ts...> const& lhs, std::tuple<Ts...> const& rhs );
template<class T, class...LowPriority>
int cmp( T const& lhs, T const& rhs, LowPriority&&... );
template<class...Ts, std::size_t...Is>
int tuple_cmp( std::tuple<Ts...> const& lhs, std::tuple<Ts...> const& rhs, std::index_sequence<Is...> ) {
int result = 0;
( (result = cmp( std::get<Is>(lhs), std::get<Is>(rhs) )) && ... );
return result;
}
template<class...Ts>
int cmp( std::tuple<Ts...> const& lhs, std::tuple<Ts...> const& rhs ) {
return tuple_cmp( lhs, rhs, std::make_index_sequence<sizeof...(Ts)>{} );
}
template<class T, class...LowPriority>
int cmp( T const& lhs, T const& rhs, LowPriority&&... ) {
if (lhs < rhs) return -1;
if (rhs < lhs) return 1;
return 0;
}
}
which is yet more arcane code, but you get a simpler bob
: 这是更神秘的代码,但你得到一个更简单的
bob
:
struct bob : utils::use_cmp<bob>
{
int x, y;
bob( int x_, int y_ ):x(x_), y(y_) {}
friend auto as_tie(bob const& b) {
return std::tie(b.x,b.y);
}
friend int cmp( bob const& lhs, bob const& rhs ) {
return utils::cmp( as_tie(lhs), as_tie(rhs) );
}
};
Note, however, that all of this is done and better by operator<=>
in c++20 . 但请注意,所有这些都是由c ++ 20中的
operator<=>
完成的。
Live example . 实例 。
This is similar to the approach boost::operators uses to write these operators for you. 这与boost ::运算符用于为您编写这些运算符的方法类似。
Using an obvious notation, " >
|| ==
" is actually an over-requirement for >=
. 使用明显的表示法,“
>
|| ==
”实际上是对>=
的过度要求。
Although note that for all the relational operators, you only actually need <
, since equivalence is established if a < b
and b < a
are both false. 虽然请注意,对于所有关系运算符,您实际上只需要
<
,因为如果a < b
和b < a
都为假,则建立等价。 In fact this is one of the concepts used in ordered C++ standard library containers. 实际上,这是有序C ++标准库容器中使用的概念之一。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.