Poniższy kod kompiluje się dobrze z clang-trunk w trybie c ++ 17, ale psuje się w trybie c ++ 2a (nadchodzące 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{});
}
Kompiluje się również dobrze z gcc-trunk lub clang-9.0.0: https://godbolt.org/z/8GGT78
Błąd z clang-trunk i -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)
Rozumiem, że C ++ 20 pozwoli jedynie na przeciążenie, operator==
a kompilator wygeneruje automatycznie operator!=
, negując wynik operator==
. O ile rozumiem, działa to tylko tak długo, jak typ zwrotu jest bool
.
Źródłem problemu jest to, że w Eigen deklarujemy zestaw operatorów ==
, !=
, <
, ... między Array
obiektami lub Array
i skalary, które obie strony (wyraz) tablicę bool
(które następnie można uzyskać element mądry lub wykorzystywane w inny sposób ). Na przykład,
#include <Eigen/Core>
int main()
{
Eigen::ArrayXd a(10);
a.setRandom();
return (a != 0.0).any();
}
W przeciwieństwie do mojego powyższego przykładu, nawet nie działa z gcc-trunk: https://godbolt.org/z/RWktKs . Nie udało mi się jeszcze zredukować tego do przykładu innego niż Eigen, który zawodzi zarówno w przypadku clang-trunk, jak i gcc-trunk (przykład na górze jest dość uproszczony).
Raport dotyczący pokrewnego problemu: https://gitlab.com/libeigen/eigen/issues/1833
Moje aktualne pytanie: czy to rzeczywiście przełomowa zmiana w C ++ 20 (i czy istnieje możliwość przeciążenia operatorów porównania, aby zwrócić obiekty meta), czy może jest to regresja w clang / gcc?