Der folgende Code lässt sich gut mit Clang-Trunk im C ++ 17-Modus kompilieren, bricht jedoch im C ++ 2a-Modus (bevorstehendes C ++ 20) ab:
// 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{});
}
Es lässt sich auch gut mit gcc-trunk oder clang-9.0.0 kompilieren: https://godbolt.org/z/8GGT78
Der Fehler mit Clang-Trunk und -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)
Ich verstehe, dass C ++ 20 es möglich macht, nur zu überladen, operator==
und der Compiler automatisch generiert, operator!=
indem er das Ergebnis von negiert operator==
. Soweit ich weiß, funktioniert dies nur, solange der Rückgabetyp ist bool
.
Die Ursache des Problems ist , dass in Eigen wir eine Reihe von Operatoren erklären ==
, !=
, <
, ... zwischen Array
Objekten oder Array
und Skalare, die Rückkehr (ein Ausdruck) ein Array von bool
(die dann elementweise zugegriffen werden kann, oder anderweitig verwendet werden ). Z.B,
#include <Eigen/Core>
int main()
{
Eigen::ArrayXd a(10);
a.setRandom();
return (a != 0.0).any();
}
Im Gegensatz zu meinem obigen Beispiel schlägt dies sogar mit gcc-trunk fehl: https://godbolt.org/z/RWktKs . Ich habe es noch nicht geschafft, dies auf ein Nicht-Eigen-Beispiel zu reduzieren, das sowohl im Clang-Trunk als auch im Gcc-Trunk fehlschlägt (das Beispiel oben ist ziemlich vereinfacht).
Zugehöriger Problembericht: https://gitlab.com/libeigen/eigen/issues/1833
Meine eigentliche Frage: Ist dies tatsächlich eine bahnbrechende Änderung in C ++ 20 (und besteht die Möglichkeit, die Vergleichsoperatoren zu überladen, um Meta-Objekte zurückzugeben), oder handelt es sich eher um eine Regression in clang / gcc?