非ブール戻り値と等価比較を過負荷時に打ち鳴らすトランク/ gccのトランクでのC ++ 20または回帰の変化を壊しますか?

chtz:

次のコードは、C ++ 17モードで打ち鳴らすトランクと罰金をコンパイルしますが、C ++ 2A(次期C ++ 20)モードでの休憩:

// Meta struct describing the result of a comparison
struct Meta {};

struct Foo {
    Meta operator==(const Foo&) {return Meta{};}
    Meta operator!=(const Foo&) {return Meta{};}
};

int main()
{
    Meta res = (Foo{} != Foo{});
}

また、GCC-トランクまたは打ち鳴らす-9.0.0で罰金をコンパイルします。https://godbolt.org/z/8GGT78

打ち鳴らすトランクとでエラー-std=c++2a

<source>:12:19: error: use of overloaded operator '!=' is ambiguous (with operand types 'Foo' and 'Foo')
    Meta res = (f != g);
                ~ ^  ~
<source>:6:10: note: candidate function
    Meta operator!=(const Foo&) {return Meta{};}
         ^
<source>:5:10: note: candidate function
    Meta operator==(const Foo&) {return Meta{};}
         ^
<source>:5:10: note: candidate function (with reversed parameter order)

私はC ++ 20にのみ、過負荷にそれが可能になることを理解operator==し、コンパイラが自動的に生成されoperator!=た結果を否定することでoperator==私の知る限り理解し、これはのみ限り、戻り値の型があるとして動作しますbool

問題の原因は、固有に、我々は、オペレータのセットを宣言することで==!=<の間、... Arrayオブジェクト又はArrayおよびスカラー、リターン(の発現)のアレイbool次いで要素ごとにアクセスすること、またはそうでなければ使用することができます( )。例えば、

#include <Eigen/Core>
int main()
{
  Eigen::ArrayXd a(10);
  a.setRandom();
  return (a != 0.0).any();
}

:この上記の私の例とは対照的にでもgccのトランクで失敗しhttps://godbolt.org/z/RWktKs私が打ち鳴らすトランクとgcc-トランクの両方に障害が発生した非固有の例、(一番上の例は、かなり簡略化されている)にこれを減らすために、まだ管理していません。

関連問題のレポート:https://gitlab.com/libeigen/eigen/issues/1833

私の実際の質問:これはC ++ 20での互換性に影響する変更実際に(およびメタオブジェクトを返すために、比較演算子をオーバーロードする可能性がある)、または、それは可能性が高い打ち鳴らす/ gccの回帰のですか?

TC:

固有の問題は、以下に減らすために表示されます。

using Scalar = double;

template<class Derived>
struct Base {
    friend inline int operator==(const Scalar&, const Derived&) { return 1; }
    int operator!=(const Scalar&) const;
};

struct X : Base<X> {};

int main() {
    X{} != 0.0;
}

表現のための2つの候補であります

  1. から書き換え候補 operator==(const Scalar&, const Derived&)
  2. Base<X>::operator!=(const Scalar&) const

ごと[over.match.funcs] / 4、などoperator!=の範囲にインポートされなかったXことにより、使用宣言、#2のための暗黙のオブジェクトパラメータのタイプがありますconst Base<X>&その結果、#1は、その引数(完全一致ではなく、派生する塩基変換)のためのより良い暗黙的な変換配列を有します。#1を選択すると、その後、病気に形成されたプログラムをレンダリングします。

可能な修正:

  • 追加using Base::operator!=;するDerived、または
  • 変更operator==取るconst Base&のではなくをconst Derived&

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=369785&siteId=1