C++では、より大きい(または等しい)演算子( "> =")に対して、等しい( "=")およびより大きい( ">")演算子をオーバーロードして、以上( "> =")?または、機能を持たせるために演算子( "> =")をオーバーロードする必要がありますか?
明らかな表記法「>
|| ==
"は、実際には>=
。
all関係演算子の場合、実際に必要なのは<
、a < b
およびb < a
は両方とも偽です。実際、これは、順序付けられたC++標準ライブラリコンテナで使用される概念の1つです。
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 演算子のオーバーロードの基本的なルールとイディオムは何ですか?
演算子が等しい( "=")で十分ですか
C++の等しい演算子は==
です
または、演算子( "> =")に機能を持たせるために演算子をオーバーロードする必要がありますか?
機能の意味によって異なります。 operator==
とoperator>
を定義すると、コンパイラーはoperator>=
を自動的に生成しますか?いいえ、ありません。既存の演算子を使用して実装する必要があります。
いいえ、C++はこれらの演算子を作成しません。
それが悪いと思うなら、あなたは正しい。この吸い込みを減らすための多くの方法が行われました。それらのうち4つについて説明します。
c ++ 2 で、 operator<=>
( -way "spaceship"演算子)を正しく記述した場合、または=default
それから、<
、<=
、>=
、>
、!=
、および==
のすべてが自動的に書き込まれます。
struct bob {
int x,y;
auto operator<=>( bob const& )const = default;
};
上記のbob
には、C++によって書かれたすべての<
==
etc演算子があります。
c ++ 2 の前に、それらのすべてが必要な場合は、それらすべてを記述する必要があります。これは退屈でエラーが発生しやすくなります。
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
を使用します。これは、小さい場合は負の数、大きい場合は正の数、等しい場合は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) );
}
};
ただし、これはすべて、 c ++ 2 のoperator<=>
によって実行され、改善されることに注意してください。
実例 。
これは、 boost :: operators がこれらの演算子を作成するために使用するアプローチに似ています。