C ++の<=>演算子とは何ですか?


215

私は学ぶしようとしたが、C ++の演算子、私は上の奇妙な比較演算子につまずいcppreference.com*このように見えたテーブルに:

ここに画像の説明を入力してください

「そうですね、これらがC ++の一般的な演算子であるなら、私はそれらをよりよく学ぶ」と私は考えました。しかし、この謎を解明しようとする私の試みはすべて失敗しました。ここでも、Stack Overflowでは検索がうまくいきませんでした。

<=>C ++の間に関係はありますか?

そして、ある場合、この演算子は正確に何をしますか?

*その間、cppreference.comがそのページを更新し、<=>オペレーターに関する情報が含まれるようになりました。


82
@haccks:ああ、どうも、規格に投票されなかったものについてはたくさんの質問がありました。理由のためにC ++ 20タグがあります。この種のものは非常に話題になっています。
Nicol Bolas 2017年

1
@ cubuspl42 bar< foo::operator<=>は、<--演算子のようになる例です。
Yakk-Adam Nevraumont 2017年

8
@haccks:そうです。C ++ 11と同様に、C ++ 11を実装するコンパイラに関するタグです。C ++ 14は、C ++ 14を実装するコンパイラに関するタグです。そしてC ++ 17は、C ++ 17を実装するコンパイラに関するものです。いいえ、C ++ 20はC ++ 20に関するもののタグです。そして、この質問はC ++ 20に関するものなので、あります。タグ自体ではなく、間違ったタグwiki。
Nicol Bolas

回答:


180

これは、3者間比較演算子と呼ばれます。

P0515紙の提案によると:

新しい3者間比較演算子があり<=>ます。式a <=> bは、<0if a < bを比較し>0、if a > bを比較し==0、if abequal / equivalent を比較するオブジェクトを返します。

タイプのすべての比較を書き込むoperator<=>には、適切なカテゴリタイプを返すように記述します。

  • 戻り_orderingをあなたのタイプは自然にサポートしている場合は<、私たちは効率的に生成します<><=>===、と!=。それ以外の場合は_equalityを返し==!=を効率的に生成します 。

  • 型がa == b暗示する場合f(a) == f(b)(fが非プライベートのconstインターフェースを使用してアクセス可能な比較重視の状態のみを読み取る代替性)が強い場合は強い値を返し、そうでない場合は弱い値を返します。

cppreferenceは言います:

3者間比較演算子式の形式は次のとおりです。

lhs <=> rhs   (1)  

式は次のオブジェクトを返します

  • 比較<0するlhs < rhs
  • 比較>0するlhs > rhs
  • そして、比較し==0た場合lhsrhs同等の/同じです。

93
"compares <0"、 "compares >0"、および "compares ==0"の意味について混乱している(私がそうであった)人々にとって、これら<=>は引数に応じて、負、正、またはゼロの値を返すことを意味します。とのようstrncmpmemcmp
Cornstalks 2017年

1
@Daiにもかかわらず、両方'a' < 'a''c' < 'a'両方偽である、'a' < 'a''a' < 'c'されません。次の強い順序で正しい:a != ba < b || b < a
Revolver_Ocelot

1
@Revolver_Ocelotああ、それはのように生成/定義することができますので、operator==(T x, T y) { return !(x < y) && !(y < x); }operator!=(T x, T y) { return (x < y) || (y < x); }AH-haの- !もちろん==、比較を2回呼び出すため、これはtrueほど効率的ではありませんが、それでも適切です。

3
「強いリターン」と「弱いリターン」はどういう意味ですか?
lucidbrot 2017年

2
@hkBattousaiは、オブジェクトが返されることを意味し、比較< 0するとtrue と評価されます。場合つまり、a < bその後、(a <=> b) < 0常に真です。
rmobis

116

2017年11月11日、ISO C ++委員会が採択し ハーブサッターのための提案<=> 『宇宙船』 3ウェイ比較演算子をに追加された新機能の一つとして、C ++ 20。「一貫性のある比較」というタイトルの論文で、Sutter、Maurer、およびBrownは新しいデザインの概念を示しています。提案の概要については、記事からの抜粋を以下に示します。

<=> bが比較対象返す<0の場合は<Bを、比較> 0の場合、B> 、及び比較== 0とbが等しい/等しい場合。

一般的なケース:タイプXとタイプYのすべての比較をメンバーごとのセマンティクスで書き込むには、次のように記述します。

auto X::operator<=>(const Y&) =default;

高度なケース:タイプXとタイプYのすべての比較を書き込むには、Yを受け取るoperator <=>を書き込み、必要に応じて= defaultを使用 してメンバーごとのセマンティクスを取得し、適切なカテゴリタイプを返します。

  • タイプが自然に<をサポートしている場合は_orderingを返します。対称<><=> ===!=を効率的に生成します。それ以外の場合は_equalityを返し、対称的な==および!=を効率的に生成します。
  • あなたのタイプのa == bf(a)== f(b)を意味する場合はstrong_を返します(代替可能性、fはパブリックconstメンバーを使用してアクセス可能な比較重視の状態のみを読み取ります)、そうでない場合はweak_を返し ます

比較カテゴリ

5つの比較カテゴリがstd::タイプとして定義され、それぞれに次の定義済みの値があります。

+--------------------------------------------------------------------+
|                  |          Numeric  values          | Non-numeric |
|     Category     +-----------------------------------+             |
|                  | -1   | 0          | +1            |   values    |
+------------------+------+------------+---------------+-------------+
| strong_ordering  | less | equal      | greater       |             |
| weak_ordering    | less | equivalent | greater       |             |
| partial_ordering | less | equivalent | greater       | unordered   |
| strong_equality  |      | equal      | nonequal      |             |
| weak_equality    |      | equivalent | nonequivalent |             |
+------------------+------+------------+---------------+-------------+

これらのタイプ間の暗黙的な変換は、次のように定義されています。

  • strong_ordering値が{ 、、}のless場合equalgreater暗黙的に次のように変換されます:
    • weak_ordering値を{ lessequivalentgreater}
    • partial_ordering値を{ lessequivalentgreater}
    • strong_equality値を{ unequalequalunequal}
    • weak_equality値を{ nonequivalentequivalentnonequivalent}
  • weak_ordering値が{ 、、}のless場合equivalentgreater暗黙的に次のように変換されます:
    • partial_ordering値を{ lessequivalentgreater}
    • weak_equality値を{ nonequivalentequivalentnonequivalent}
  • partial_ordering値と{ lessequivalentgreaterunordered}暗黙的に変換します。
    • weak_equality値を{ nonequivalentequivalentnonequivalentnonequivalent}
  • strong_equality値が{ equalunequal}の場合、暗黙的に次のように変換されます:
    • weak_equality値{ equivalentnonequivalent}

三者比較

<=>トークンが導入されます。文字シーケンスは、古いソースコードではに<=>トークン化され<= >ます。たとえばX<&Y::operator<=>、意味を保持するためにスペースを追加する必要があります。

オーバーロード可能な演算子<=>は3者間比較関数であり、よりも優先順位が高く<、低くなり<<ます。リテラルと比較できる型を返しますが、0式テンプレートをサポートするなど、他の戻り型も許可されます。<=>言語および標準ライブラリで定義されたすべての演算子は、前述の5つのstd::比較カテゴリタイプの1つを返します。

言語タイプについては、以下の組み込みの<=>同じタイプの比較が提供されています。特に断りのない限り、すべてconstexprです。これらの比較は、スカラーの昇格/変換を使用して異種混合で呼び出すことはできません。

  • 以下のためにbool、一体型、およびポインタ型、<=>戻りますstrong_ordering
  • ポインター型の場合、さまざまなcv修飾と派生からベースへの変換で、同種組み込みを呼び出すことができ<=>、組み込み異種がありoperator<=>(T*, nullptr_t)ます。同じオブジェクト/割り当てへのポインタの比較のみが定数式です。
  • 基本的な浮動小数点型の場合、を<=>返しますpartial_ordering。引数をより大きな浮動小数点型に拡張することにより、異種で呼び出すことができます。
  • 列挙<=>型の場合、列挙型の基になる型と同じものを返します<=>
  • の場合nullptr_t<=>戻り値はstrong_ordering常に生成されequalます。
  • コピー可能アレイに対して、T[N] <=> T[N]同じ型を返すT<=>と行う辞書式要素ごとの比較。<=>他のアレイにはありません。
  • 以下のためにvoid何もありません<=>

このオペレーターの内部の仕組みをよりよく理解するには、元の論文をお読みください。これは私が検索エンジンを使って見つけたものです。


1
まるでcppはもう十分に複雑ではなかったかのように。なぜ単純に比較メソッドを作成しないのですか...
Leandro

6
@Leandro宇宙船演算子その比較方法です。さらに、それは正常に機能し、他の6つの比較演算子を書き込み(または削除)します。6つのボイラープレートに記述された1つの比較演算子関数を使用します。
匿名の

_equality型が消滅したことに注意してください<=>。4つの関係演算子ではうまく機能しますが、2つの等価演算子ではうまく機能しないことがわかりました(ただし、それらすべてが必要な一般的なケースをサポートするための強力な構文上の砂糖があります)。
デイビスニシン

12

参照されているWebページが変更されたため、この回答は無関係になりました

あなたが参照しているウェブページが壊れていました。その日はたくさん編集されていて、異なる部分が同期していませんでした。私がそれを見ていたときの状況は、

ページの上部に、現在存在する比較演算子(C ++ 14)が一覧表示されます。そこはありません<=>

ページの下部に、同じ演算子がリストされているはずですが、間違えてこの将来の提案を追加しました。

gcc<=>まだ(そして、と一緒-std=c++14に)を知らないので、を意味していると思われますa <= > b。これはエラーメッセージの説明です。

5年後に同じことを試みると、おそらく次のような、より適切なエラーメッセージが表示されます。 <=> not part of C++14.


1
OPがリンクするWebページは、リンクする別のページと同様に正しいです。<=>演算子を(C ++ 20以降)ラベルで修飾し、標準のどのバージョンを使用するかを通知します。標準のラベル付けは、cppreference.comが従う規則です。もちろん、タイムマシンに戻ってそれをサポートするコンパイラーはありませんが、cpprefernceは(正しく)何を期待するかを指示します。
スペンサー

はい、しかし...答えではありません。あなたはコメントしています...または何か。
qlp

2
質問と同じWebページにリンクするつもりでしたが、見落としました。私は他の答えがしなかった質問の部分に答えたと思います。他の人がすでにそれに答えていたので、私は主な太字の質問を無視しました。
Stig Hemmer
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.