Наступний код добре поєднує кланг-магістраль у режимі 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/isissue/1833
Моє актуальне запитання: чи насправді це неперервна зміна C ++ 20 (і чи є можливість перевантажувати оператори порівняння, щоб повернути мета-об'єкти), чи це більше ймовірність регресії в clang / gcc?