C++ 大于或等于运算符
C++ greater than or equal to operator
在 C++ 中,对于大于或等于 (">=") 的运算符,重载等于 ("=") 和大于 (">") 的运算符是否足以具有更大的功能大于或等于(“>=”)?或者我是否需要重载运算符 (">=") 以使其具有功能?
使用明显的符号,“>
|| ==
”实际上是对 >=
.
的过度要求
虽然请注意,对于 所有 关系运算符,您实际上只需要 <
,因为如果 a < b
和 b < a
就建立了等价关系都是假的。事实上,这是有序 C++ 标准库容器中使用的概念之一。
is it enough to have the operators equal ("=")
C++ 中的等于运算符是 ==
OR do I need to overload the operator (">=") to have functionality for it?
这取决于您所说的功能。如果你的意思是如果你定义 operator==
和 operator>
编译器会自动为你生成 operator>=
吗?不,它不会,你必须使用或不使用现有的运营商来实现它。
operator >=
不是 operator >
和 operator =
的组合。 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);}
来自 sbi answer on What are the basic rules and idioms for operator overloading?
不,C++ 不会为您编写这些运算符。
如果您认为这很糟糕,那您是对的。已经有很多方法可以减少这种情况。我将谈论其中的 4 个。
等待c++20
在c++20中,如果你写operator<=>
(3-way“宇宙飞船”运算符)正确地,或者 =default
它,那么 <
、<=
、>=
、>
、!=
和 ==
都将是为你而写。
struct bob {
int x,y;
auto operator<=>( bob const& )const = default;
};
上面的 bob
现在每个 <
==
等运算符都由 C++ 编写。
随便写
在c++20之前,如果你想要所有的,你必须把它们都写下来。这很乏味且容易出错。
使用 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);
}
};
甚至
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);
}
};
因为tuple
进行了适当的词法比较;编写没有错误的词典比较很烦人。
用你的方式进行元编程
比较字符串时通常使用strcmp
。 returns 如果小于则为负数,如果大于则为正数,如果等于则为 0。这种模式比重复 <
或 ==
更有效。
使单个 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); }
};
}
现在假设我们有一个类型:
struct bob {
int x, y;
};
并且我们希望能够在其上使用比较运算符:
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;
}
};
并使用 CRTP bob
的魔力,现在已经为它编写了每个比较运算符。
烦人的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;
}
}
这是更难懂的代码,但你会得到一个更简单的 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) );
}
};
但是请注意,所有这些都由 operator<=>
在 c++20 中完成并且做得更好。
使用别人的解决方案
这类似于 boost::operators 用来为您编写这些运算符的方法。
在 C++ 中,对于大于或等于 (">=") 的运算符,重载等于 ("=") 和大于 (">") 的运算符是否足以具有更大的功能大于或等于(“>=”)?或者我是否需要重载运算符 (">=") 以使其具有功能?
使用明显的符号,“>
|| ==
”实际上是对 >=
.
虽然请注意,对于 所有 关系运算符,您实际上只需要 <
,因为如果 a < b
和 b < a
就建立了等价关系都是假的。事实上,这是有序 C++ 标准库容器中使用的概念之一。
is it enough to have the operators equal ("=")
C++ 中的等于运算符是 ==
OR do I need to overload the operator (">=") to have functionality for it?
这取决于您所说的功能。如果你的意思是如果你定义 operator==
和 operator>
编译器会自动为你生成 operator>=
吗?不,它不会,你必须使用或不使用现有的运营商来实现它。
operator >=
不是 operator >
和 operator =
的组合。 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);}
来自 sbi answer on What are the basic rules and idioms for operator overloading?
不,C++ 不会为您编写这些运算符。
如果您认为这很糟糕,那您是对的。已经有很多方法可以减少这种情况。我将谈论其中的 4 个。
等待c++20
在c++20中,如果你写operator<=>
(3-way“宇宙飞船”运算符)正确地,或者 =default
它,那么 <
、<=
、>=
、>
、!=
和 ==
都将是为你而写。
struct bob {
int x,y;
auto operator<=>( bob const& )const = default;
};
上面的 bob
现在每个 <
==
等运算符都由 C++ 编写。
随便写
在c++20之前,如果你想要所有的,你必须把它们都写下来。这很乏味且容易出错。
使用 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);
}
};
甚至
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);
}
};
因为tuple
进行了适当的词法比较;编写没有错误的词典比较很烦人。
用你的方式进行元编程
比较字符串时通常使用strcmp
。 returns 如果小于则为负数,如果大于则为正数,如果等于则为 0。这种模式比重复 <
或 ==
更有效。
使单个 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); }
};
}
现在假设我们有一个类型:
struct bob {
int x, y;
};
并且我们希望能够在其上使用比较运算符:
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;
}
};
并使用 CRTP bob
的魔力,现在已经为它编写了每个比较运算符。
烦人的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;
}
}
这是更难懂的代码,但你会得到一个更简单的 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) );
}
};
但是请注意,所有这些都由 operator<=>
在 c++20 中完成并且做得更好。
使用别人的解决方案
这类似于 boost::operators 用来为您编写这些运算符的方法。