等式演算子で既存のコードを壊すC ++ 20の動作?

105
sehe 2021-01-10 14:09.

この質問のデバッグ中にこれに遭遇しました。

ブースト演算子を使用するように切り詰めました:

  1. コンパイラエクスプローラーC ++ 17 C ++ 20

    #include <boost/operators.hpp>
    
    struct F : boost::totally_ordered1<F, boost::totally_ordered2<F, int>> {
        /*implicit*/ F(int t_) : t(t_) {}
        bool operator==(F const& o) const { return t == o.t; }
        bool operator< (F const& o) const { return t <  o.t; }
      private: int t;
    };
    
    int main() {
        #pragma GCC diagnostic ignored "-Wunused"
        F { 42 } == F{ 42 }; // OKAY
        42 == F{42};         // C++17 OK, C++20 infinite recursion
        F { 42 } == 42;      // C++17 OK, C++20 infinite recursion
    }
    

    このプログラムは、GCCとClangの両方でC ++ 17(ubsan / asanが有効)で正常にコンパイルおよび実行されます。

  2. 暗黙のコンストラクターをに変更するexplicitと、問題のある行は明らかにC ++ 17でコンパイルされなくなります。

驚くべきことに、両方のバージョンはC ++ 20(v1およびv2)でコンパイルされますが、C ++ 17ではコンパイルされない2行で無限再帰(最適化レベルに応じてクラッシュまたはタイトループ)が発生します。

明らかに、C ++ 20にアップグレードすることによって忍び寄るこの種のサイレントバグは気になります。

質問:

  • このc ++ 20の動作は準拠していますか(私はそう期待しています)
  • 何が干渉しているのですか?c ++ 20の新しい「宇宙船演算子」のサポートが原因である可能性がありますが、このコードの動作がどのように変わるはわかりません。

1 answers

81
Barry 2021-01-10 14:27.

実際、C ++ 20は残念ながら、このコードを無限に再帰的にします。

縮小した例を次に示します。

struct F {
    /*implicit*/ F(int t_) : t(t_) {}

    // member: #1
    bool operator==(F const& o) const { return t == o.t; }

    // non-member: #2
    friend bool operator==(const int& y, const F& x) { return x == y; }

private:
    int t;
};

を見てみましょう42 == F{42}

C ++ 17では、非メンバー候補(#2)という1つの候補しかなかったので、それを選択します。その本体は、x == y会員候補(:、それ自体が唯一つの候補有する#1)暗黙的に変換することを含むy内をF。そして、そのメンバー候補は2つの整数メンバーを比較し、これはまったく問題ありません。

C ++ 20では、最初の式42 == F{42}2つの候補があります。#2以前のように非メンバー候補()と、逆メンバー候補(#1逆)の両方です。#2がより適切に一致します。変換を呼び出すのではなく、両方の引数を正確に一致させるため、選択されます。

ただし、x == y現在は2つの候補があります。メンバー候補(#1)と、逆にされた非メンバー候補(#2逆)です。#2以前より良い一致であったのと同じ理由で、再びより良い一致です:変換は必要ありません。したがって、y == x代わりに評価します。無限再帰。

逆転されていない候補者は、逆転された候補者よりも好まれますが、タイブレーカーとしてのみです。より良い変換シーケンスが常に最初です。


わかりました。どうすれば修正できますか?最も簡単なオプションは、非メンバー候補を完全に削除することです。

struct F {
    /*implicit*/ F(int t_) : t(t_) {}

    bool operator==(F const& o) const { return t == o.t; }

private:
    int t;
};

42 == F{42}ここでは、として評価されF{42}.operator==(42)ます。これは正常に機能します。

非メンバー候補を保持したい場合は、その逆の候補を明示的に追加できます。

struct F {
    /*implicit*/ F(int t_) : t(t_) {}
    bool operator==(F const& o) const { return t == o.t; }
    bool operator==(int i) const { return t == i; }
    friend bool operator==(const int& y, const F& x) { return x == y; }

private:
    int t;
};

これにより42 == F{42}、非メンバー候補が選択されますがx == y、本文ではメンバー候補が優先され、通常の同等性が実行されます。

この最後のバージョンでは、非メンバー候補を削除することもできます。以下は、すべてのテストケースで再帰なしでも機能します(これは、今後C ++ 20で比較を作成する方法です)。

struct F {
    /*implicit*/ F(int t_) : t(t_) {}
    bool operator==(F const& o) const { return t == o.t; }
    bool operator==(int i) const { return t == i; }

private:
    int t;
};

Related questions

MORE COOL STUFF

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは、夫に会ったとき、典型的な交際のアドバイスに逆らいました。

マイケルシーンが非営利の俳優である理由

マイケルシーンが非営利の俳優である理由

マイケルシーンは非営利の俳優ですが、それは正確にはどういう意味ですか?

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

特徴的なスターのコリン・エッグレスフィールドは、RomaDrama Liveでのスリル満点のファンとの出会いについて料理しました!加えて、大会での彼のINSPIREプログラム。

「たどりつけば」をオンラインでストリーミングできない理由

「たどりつけば」をオンラインでストリーミングできない理由

ノーザンエクスポージャーが90年代の最も人気のある番組の1つになった理由を確認するには、Blu-rayまたはDVDプレーヤーをほこりで払う必要があります。

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖は、世界で2番目に大きいボイリング湖です。そこにたどり着くまでのトレッキングは大変で長いですが、努力する価値は十分にあります。

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

サロンからのヘアトリミングや個人的な寄付は、油流出を吸収して環境を保護するのに役立つマットとして再利用できます。

科学者は髪が灰色になる理由の別の可能な説明を見つけます

科学者は髪が灰色になる理由の別の可能な説明を見つけます

このネズミのグリズリした毛皮は、いつか人々が白斑と呼ばれるまれな状態を発症する理由を説明するのに役立つかもしれません。科学者たちは、白斑と呼ばれるまれな汚名を着せられた状態である無着色の皮膚の斑点に悩まされる人もいれば、髪が灰色になる理由を説明できる新たに発見されたメカニズムに遭遇したと考えています。

新しい若いテロリストコレクションの内部のこの外観で、神秘的で残忍な陰謀に飛び込む

新しい若いテロリストコレクションの内部のこの外観で、神秘的で残忍な陰謀に飛び込む

若いテロリストの野生のアンチヒーロー、セラに会いましょう。ほぼ3年前、Black Mask Studiosは、残忍で政治的な色合いのスリラーであるYoungTerroristsと波を起こしました。

Huluが周りを見回し、The Handmaid'sTaleを第3シーズンに更新します

Huluが周りを見回し、The Handmaid'sTaleを第3シーズンに更新します

ハンドメイドの物語のエリザベスモス昨夜、アイオワ上院は、胎児の心拍が検出された後、ほとんどの妊娠中絶を禁止する、いわゆる「心拍」法案を早急に追跡しました。妊娠。また、HuluはThe Handmaid'sTaleを第3シーズンに更新することを決定しました。

ラストコール:どのように風邪と戦うのですか?

ラストコール:どのように風邪と戦うのですか?

これは実際に機能しますか?病気になってから久しぶりですが(ジンクス!)、今朝目が覚めたとき、副鼻腔の奥にひどい痛みを感じ、病気になりそうです。風邪が嫌いです。

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

イーサン プラスの誕生日のお祝いは、TLC のウェルカム トゥ プラスビルのシーズン 4 のフィナーレで、戦争中の母親のキム プラスと妻のオリビア プラスを結びつけました。

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

ケイト・ミドルトンはロンドンの水辺で一日を過ごし、さらにジェニファー・ロペス、ジュリアン・ハフなど

ケイト・ミドルトンはロンドンの水辺で一日を過ごし、さらにジェニファー・ロペス、ジュリアン・ハフなど

ケイト・ミドルトンはロンドンの水辺で 1 日を過ごし、ジェニファー・ロペス、ジュリアン・ハフなども。ハリウッドからニューヨークまで、そしてその間のあらゆる場所で、お気に入りのスターの活躍をご覧ください!

ウィスコンシン川でのナイフ攻撃で 17 歳の少年が刺されて死亡、他の 4 人が負傷したままになっている

ウィスコンシン川でのナイフ攻撃で 17 歳の少年が刺されて死亡、他の 4 人が負傷したままになっている

捜査官は、グループと容疑者が攻撃の前にお互いを知っていたかどうかを調べています

実際に変換するコンテンツ戦略を作成することを想像してみてください。それが可能だ。

実際に変換するコンテンツ戦略を作成することを想像してみてください。それが可能だ。

2021 年には、サービスを提供する顧客と顧客に伝えるストーリーについて知っていることをすべて再考することをお勧めします。あとずさりする。

マンモスロスは私の心を愛に開いた

マンモスロスは私の心を愛に開いた

フェリックス ザ キャットの 9 歳の誕生日の日に、大人になってからの最大の損失の 1 つである 2013 年のソフィーを思い出します。私はこのエッセイを書き、2013 年にこのプラットフォームで簡単に共有しました。

あなたがインターネットがあなたに望んでいる人になれないとき

あなたがインターネットがあなたに望んでいる人になれないとき

私は「列車事故」という言葉が嫌いです。人々は自分自身の道徳的羅針盤に安らぎを覚え、そうすることで自分自身が判断を下していることに気づきます。

DFINITY ブロックチェーンの分散型クラウド ビジョン

編集者注: アーカイブ目的で保存されている DFINITY ブログの古い資料を表示しています。

DFINITY ブロックチェーンの分散型クラウド ビジョン

この投稿では、DFINITY チームの分散型クラウドのビジョンと、それが従来のブロックチェーンやアマゾン ウェブ サービスなどの既存のクラウド プロバイダーとどのように関連しているかを探ります。大規模なネットワークによって適用される DFINITY テクノロジのデモンストレーションが 2017 年の秋に行われ、その後、非営利財団を支援するための主要な資金調達が行われ、「オープン クラウド」ネットワークは 2018 年の初夏に開始される予定です。 .

Language