Следующий код прекрасно компилируется с clang-trunk в режиме 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-trunk или clang-9.0.0: https://godbolt.org/z/8GGT78.
Ошибка с clang-trunk и -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-trunk: https://godbolt.org/z/RWktKs . Я еще не успел свести это к не-собственному примеру, который терпит неудачу как в clang-trunk, так и в gcc-trunk (пример вверху довольно упрощен).
Связанный отчет о проблеме: https://gitlab.com/libeigen/eigen/issues/1833
Мой актуальный вопрос: действительно ли это серьезное изменение в C ++ 20 (и есть ли возможность перегрузить операторы сравнения для возврата мета-объектов) или это более вероятно регрессия в clang / gcc?