次のコードは、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の回帰のですか?
固有の問題は、以下に減らすために表示されます。
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つの候補であります
- から書き換え候補
operator==(const Scalar&, const Derived&)
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&
。