比較演算子
引数を比較します。
演算子の名前 | 構文 | オーバーロード可能 | プロトタイプの例 (class T に対して) | |
---|---|---|---|---|
メンバ関数として | 自由関数として | |||
等しい | a == b
|
Yes | bool T::operator ==(const T2 &b) const; | bool operator ==(const T &a, const T2 &b); |
等しくない | a != b
|
Yes | bool T::operator !=(const T2 &b) const; | bool operator !=(const T &a, const T2 &b); |
小さい | a < b
|
Yes | bool T::operator <(const T2 &b) const; | bool operator <(const T &a, const T2 &b); |
大きい | a > b
|
Yes | bool T::operator >(const T2 &b) const; | bool operator >(const T &a, const T2 &b); |
小さいまたは等しい | a <= b
|
Yes | bool T::operator <=(const T2 &b) const; | bool operator <=(const T &a, const T2 &b); |
大きいまたは等しい | a >= b
|
Yes | bool T::operator >=(const T2 &b) const; | bool operator >=(const T &a, const T2 &b); |
三方比較 (C++20) | a <=> b
|
Yes | /*see description*/ T::operator <=>(const T2 &b) const; | /*see description*/ operator <=>(const T &a, const T2 &b); |
|
目次 |
[編集] 二方比較
二方比較演算子の式は以下の形式を持ちます。
lhs < rhs
|
(1) | ||||||||
lhs > rhs
|
(2) | ||||||||
lhs <= rhs
|
(3) | ||||||||
lhs >= rhs
|
(4) | ||||||||
lhs == rhs
|
(5) | ||||||||
lhs != rhs
|
(6) | ||||||||
true
、そうでなければ false
を返します。true
、そうでなければ false
を返します。true
、そうでなければ false
を返します。true
、そうでなければ false
を返します。true
、そうでなければ false
を返します。true
、そうでなければ false
を返します。すべての場合において、組み込みの演算子に対しては、左辺値から右辺値、配列からポインタおよび関数からポインタへの標準変換の後、 lhs と rhs は以下のいずれかでなければなりません。
- 算術型または列挙型 (後述の算術比較演算子を参照してください)
- ポインタ型 (後述のポインタ比較演算子を参照してください)
上記の標準変換の前に両方の被演算子が配列型であった場合の比較は非推奨です。 (C++20以上)
いずれの場合でも、結果は bool
の prvalue です。
[編集] 算術比較演算子
被演算子が算術型または列挙型 (スコープ付きまたはスコープなし) の場合、算術演算子のルールに従って両方の被演算子に対して通常の算術変換が行われます。 変換後、その値が比較されます。
[編集] 例
#include <iostream> int main() { std::cout << std::boolalpha; int n = -1; int n2 = 1; std::cout << " -1 == 1? " << (n == n2) << '\n' << "Comparing two signed values:\n" << " -1 < 1? " << (n < n2) << '\n' << " -1 > 1? " << (n > n2) << '\n'; unsigned int u = 1; std::cout << "Comparing signed and unsigned:\n" << " -1 < 1? " << (n < u) << '\n' << " -1 > 1? " << (n > u) << '\n'; unsigned char uc = 1; std::cout << "Comparing signed and smaller unsigned:\n" << " -1 < 1? " << (n < uc) << '\n' << " -1 > 1? " << (n > uc) << '\n'; }
出力:
-1 == 1? false Comparing two signed values: -1 < 1? true -1 > 1? false Comparing signed and unsigned: -1 < 1? false -1 > 1? true Comparing signed and smaller unsigned: -1 < 1? true -1 > 1? false
[編集] ポインタ比較演算子
比較演算子は、2つのポインタ (またはメンバポインタ (operator== および operator!= に対してのみ))、またはポインタとヌルポインタ定数、または2つのヌルポインタ定数 (ただし少なくとも片方が std::nullptr_t でなければなりません (ヌルとヌルの比較は算術比較のルールに従います)) (C++14未満)を比較するために使用することができます。
まず、合成ポインタ型を得るために、両方の被演算子にポインタ変換 (引数がメンバポインタの場合はメンバポインタ変換)、関数ポインタ変換 (C++17以上)、および修飾変換が以下のように適用されます。
T
へのポインタの場合、合成型は cv12 void へのポインタです。 ただし T
は何らかのオブジェクト型または void で、 cv12 は cv1 と cv2 の和です。
4) 両方の被演算子が同じ型への cv 修飾が異なるポインタの場合、合成型は引数の cv 修飾の和の cv 修飾を持つ、その同じ型へのポインタです。
|
(C++14未満) |
4) 被演算子の型が T1 (または cv 修飾された T1) へのポインタ P1 と T2 (または cv 修飾された T2) へのポインタ P2 の場合、 T1 が T2 と同じであるか T2 の基底クラスであれば、合成ポインタ型は P1 と P2 の cv 結合された型です。 そうでなく、 T2 が T1 の基底クラスであれば、合成ポインタ型は P2 と P1 の cv 結合された型です。
5) 被演算子の型が U1 (または cv 修飾された U1) の T1 型メンバへのポインタ MP1 と U2 (または cv 修飾された U2) の T2 型メンバへのポインタ MP2 の場合、 T1 が T2 と同じであるかその派生であれば、合成ポインタ型 MP1 と MP2 の cv 結合された型です。 そうでなく、 T2 が T1 の派生であれば、合成ポインタ型は MP2 と MP1 の cv 結合された型です。
6) 被演算子 P1 と P2 の型が多段の混合ポインタと同じ段数のメンバポインタ型で、その任意の段における cv 修飾が異なるだけの場合、合成ポインタ型は P1 と P2 の cv 結合された型です。
上の定義において、2つのポインタ型 P1 と P2 の cv 結合された型とは、 P1 と同じ段数を持ち、そのすべての段において、 cv 修飾が以下のように設定されていることを除いて P1 と同じ型を持つ型です。 a) 最上段以外のすべての段において、その段の P1 と P2 の cv 修飾の和になります。
b) 任意の段における結果の cv 修飾が同じ段の P1 または P2 の cv 修飾と異なる場合、その段と最上段の間のすべての段に const が追加されます。
例えば、 void* と const int* の合成ポインタ型は const void* で、 int** と const int** の合成ポインタ型は const int* const*です。 C++14 までは int** と const int** は比較できなかったことに注意してください。 |
(C++14以上) |
上記に加えて、関数ポインタ型と noexcept 関数ポインタ型の合成ポインタ型は (その関数型が同じであれば) 関数ポインタ型になります。 |
(C++17以上) |
これは、任意のポインタ型は void* と比較できるということを暗黙に意味します。
2つのオブジェクトへのポインタ (の変換後) の比較の結果は、以下のように定義されます。
&obj+1
は &obj
より大きいとみなされます。 (C++17以上)2つのポインタ (の変換後) の等値比較の結果は、以下のように定義されます。
メンバポインタ (の変換後) の比較の結果は、以下のように定義されます。
p<=q
と p>=q
がどちらも true
で、 p<q
と p>q
がどちらも false
の場合、ポインタ p
とポインタ q
は等しいとみなされます。
ポインタ p
がポインタ q
と比較してより大きい場合、 p>=q
, p>q
, q<=p
, q<p
はいずれも true
になり、 p<=q
, p<q
, q>=p
, q>p
はいずれも false
になります。
2つのポインタが、より大きいとも等しいとも規定されていない場合、比較の結果は未規定です。 結果は非決定的であってもよく、プログラムの同じ実行における同じ被演算子を持つ同じ式の複数回の評価に対してであっても、一貫している必要はありません。
int x, y; bool f(int* p, int* q) { return p < q; } assert(f(&x, &y) == f(&x, &y)); // may fire in a conforming implementation
ユーザ定義の演算子に対するオーバーロード解決では、昇格された算術型 L
および R
のすべての組み合わせ (列挙型を含む) について、以下の関数シグネチャがオーバーロード解決に参加します。
bool operator<(L, R); |
||
bool operator>(L, R); |
||
bool operator<=(L, R); |
||
bool operator>=(L, R); |
||
bool operator==(L, R); |
||
bool operator!=(L, R); |
||
オブジェクトへのポインタまたは関数へのポインタまたは std::nullptr_t (C++14未満) であるすべての型 P
について、以下の関数シグネチャがオーバーロード解決に参加します。
bool operator<(P, P); |
||
bool operator>(P, P); |
||
bool operator<=(P, P); |
||
bool operator>=(P, P); |
||
bool operator==(P, P); |
||
bool operator!=(P, P); |
||
メンバオブジェクトへのポインタまたはメンバ関数へのポインタまたは std::nullptr_t であるすべての型 MP
について、以下の関数シグネチャがオーバーロード解決に参加します。
bool operator==(MP, MP); |
||
bool operator!=(MP, MP); |
||
[編集] 例
#include <iostream> struct Foo { int n1; int n2; }; union Union { int n; double d; }; int main() { std::cout << std::boolalpha; char a[4] = "abc"; char* p1 = &a[1]; char* p2 = &a[2]; std::cout << "Pointers to array elements: p1 == p2 " << (p1 == p2) << ", p1 < p2 " << (p1 < p2) << '\n'; Foo f; int* p3 = &f.n1; int* p4 = &f.n2; std::cout << "Pointers to members of a class: p3 == p4 " << (p3 == p4) << ", p3 < p4 " << (p3 < p4) << '\n'; Union u; int* p5 = &u.n; double* p6 = &u.d; std::cout << "Pointers to members of a union: p5 == (void*)p6 " << (p5 == (void*)p6) << ", p5 < p6 " << (p5 < (void*)p6) << '\n'; }
出力:
Pointers to array elements: p1 == p2 false, p1 < p2 true Pointers to members of a class: p3 == p4 false, p3 < p4 true Pointers to members of a union: p5 == (void*)p6 true, p5 < p6 false
[編集] ノート
これらの演算子のグループは左結合のため、式 a<b<c は a<(b<c) や (a<b)&&(b<c) ではなく (a<b)<c と解析されます。
ユーザ定義の operator< に対する一般的な要件は狭義弱順序です。 これは特に Compare 型を使用する標準のアルゴリズムやコンテナ、 std::sort、 std::max_element、 std::map などによって要求されます。
ランダムな起源の (例えば同じ配列のメンバを指すのではない) ポインタの比較の結果は未規定ですが、多くの処理系は、連続する仮想アドレス空間内のアドレスとして実装される場合、ポインタの狭義全順序を提供します。 そうでない処理系 (例えばポインタのすべてのビットがメモリアドレスを表すのではないため比較するとき一部を無視しなければならないとか、ポインタと整数が1:1の関係でないため追加の計算が必要であるとか) は、そのような保証を持つ、ポインタに対する std::less の特殊化を提供します。 これにより、 std::set や std::map のような標準の連想コンテナで、ランダムな起源のポインタすべてをキーとして使用することが可能となります。
EqualityComparable かつ LessThanComparable である型について、 C++ 標準ライブラリは式 a == b の値である「等しい」と式 !(a < b) && !(b < a) の値である「同等」を区別します。
ポインタとヌルポインタ定数の比較は C++14 で削除されました。
void f(char * p) { if (p > 0) { ... } // C++98〜C++11 では OK、 C++14 ではコンパイルできません。 if (p > nullptr) { ... } // C++11 では OK、 C++14 ではコンパイルできません。 }
三方比較三方比較演算子は以下の形式を持ちます。
この式は以下のようなオブジェクトを返します。
被演算子の一方が bool 型で他方がそう��なければ、プログラムは ill-formed です。 被演算子がどちらも算術型の場合、または被演算子の一方がスコープなし列挙型で他方が整数型の場合、その被演算子に通常の算術変換が適用され、その後、
そうでなければ、プログラムは ill-formed です。 両方の被演算子が同じ列挙型 E である場合、この演算子は被演算子を E のベースとなる型に変換し、その変換した被演算子に <=> を適用した結果を返します。 被演算子の少なくとも一方がポインタまたはメンバへのポインタの場合、両方の被演算子を同じポインタ型に変換するために、配列からポインタへの変換、派生クラスから基底クラスへのポインタの変換、関数ポインタの変換、修飾子の変換が必要に応じて適用されます。そして結果のポインタ型がオブジェクトポインタ型の場合、 p <=> q は std::strong_ordering 型の prvalue を返します。
ユーザ定義の演算子に対するオーバーロード解決では、ポインタまたは列挙型
ただし R は上で定義されている順序カテゴリ型です。 ノート三方比較はクラス型に対して自動的に生成できます。 デフォルト比較を参照してください。 両方の被演算子が配列の場合、配列型のクラスメンバを比較するときを除いて、三方比較は ill-formed です。 unsigned int i = 1; auto r = -1 < i; // 昔からある落とし穴。 false を返します。 auto r2 = -1 <=> i; // エラー、縮小変換が必要です。
|
(C++20以上) |
[編集] 標準ライブラリ
比較演算子は標準ライブラリの多数のクラスでオーバーロードされています。
(C++20で削除) |
オブジェクトが同じ型を参照しているかどうか確認します ( std::type_info のパブリックメンバ関数)
|
(C++20で削除)(C++20で削除)(C++20) |
2つの error_code を比較します (関数) |
(C++20で削除)(C++20で削除)(C++20) |
error_condition と error_code を比較します (関数) |
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
ペア内の値を辞書的に比較します (関数テンプレート) |
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
タプル内の値を辞書的に比較します (関数テンプレート) |
(C++20で削除) |
内容を比較します ( std::bitset<N> のパブリックメンバ関数)
|
(C++20で削除) |
2つのアロケータインスタンスを比較します ( std::allocator<T> のパブリックメンバ関数)
|
別の unique_ptr または nullptr と比較します (関数テンプレート) | |
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
別の shared_ptr または nullptr と比較します (関数テンプレート) |
(C++20で削除) |
std::function を nullptr と比較します (関数テンプレート) |
2つの時間を比較します (関数テンプレート) | |
2つの time point を比較します (関数テンプレート) | |
(C++20で削除) |
2つの scoped_allocator_adaptor のインスタンスを比較します ( std::scoped_allocator_adaptor<OuterAlloc,InnerAlloc...> のパブリックメンバ関数)
|
ベースとなる std::type_info オブジェクトを比較します ( std::type_index のパブリックメンバ関数)
| |
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
2つの文字列を辞書的に比較します (関数テンプレート) |
(C++20で削除) |
2つのロケールオブジェクトが等しいかどうか比較します ( std::locale のパブリックメンバ関数)
|
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
array 内の値を辞書的に比較します (関数テンプレート) |
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
deque 内の値を辞書的に比較します (関数テンプレート) |
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
forward_list 内の値を辞書的に比較します (関数テンプレート) |
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
list 内の値を辞書的に比較します (関数テンプレート) |
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
vector 内の値を辞書的に比較します (関数テンプレート) |
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
map 内の値を辞書的に比較します (関数テンプレート) |
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
multimap 内の値を辞書的に比較します (関数テンプレート) |
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
set 内の値を辞書的に比較します (関数テンプレート) |
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
multiset 内の値を辞書的に比較します (関数テンプレート) |
(C++20で削除) |
unordered_map 内の値を比較します (関数テンプレート) |
(C++20で削除) |
unordered_multimap 内の値を比較します (関数テンプレート) |
(C++20で削除) |
unordered_set 内の値を比較します (関数テンプレート) |
(C++20で削除) |
unordered_multiset 内の値を比較します (関数テンプレート) |
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
queue 内の値を辞書的に比較します (関数テンプレート) |
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
stack 内の値を辞書的に比較します (関数テンプレート) |
ベースとなるイテレータを比較します (関数テンプレート) | |
ベースとなるイテレータを比較します (関数テンプレート) | |
(C++20で削除) |
2つの istream_iterator を比較します (関数テンプレート) |
(C++20で削除) |
2つの istreambuf_iterator を比較します (関数テンプレート) |
(C++20で削除) |
2つの複素数または複素数とスカラーを比較します (関数テンプレート) |
2つの valarray または valarray と値を比較します (関数テンプレート) | |
擬似乱数エンジンの内部状態を比較します (関数テンプレート) | |
2つの分布オブジェクトを比較します (関数) | |
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
sub_match を別の sub_match 、文字列、または文字と比較します (関数テンプレート) |
(C++20で削除) |
2つのマッチ結果内の値を辞書的に比較します (関数テンプレート) |
(C++20で削除) |
2つの regex_iterator を比較します ( std::regex_iterator<BidirIt,CharT,Traits> のパブリックメンバ関数)
|
(C++20で削除) |
2つの regex_token_iterator を比較します ( std::regex_token_iterator<BidirIt,CharT,Traits> のパブリックメンバ関数)
|
(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20で削除)(C++20) |
2つの thread::id オブジェクトを比較します (関数) |
名前空間 rel_ops は汎用の演算子 !=, >, <=, >= を提供します。
ヘッダ
<utility> で定義 | |
名前空間
std::rel_ops で定義 | |
(C++20で非推奨) |
ユーザ定義の operator== および operator< を元に比較演算子を自動生成します (関数テンプレート) |
[編集] 関連項目
一般的な演算子 | ||||||
---|---|---|---|---|---|---|
代入 | インクリメント デクリメント |
算術 | 論理 | 比較 | メンバアクセス | その他 |
a = b |
++a |
+a |
!a |
a == b |
a[b] |
a(...) |
特殊な演算子 | ||||||
static_cast は型を別の関連する型に変換します。 |
比較演算子 の C言語リファレンス
|