Đoạn mã sau biên dịch tốt với clang-trunk ở chế độ c ++ 17 nhưng bị phá vỡ ở chế độ c ++ 2a (sắp tới 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{});
}
Nó cũng biên dịch tốt với gcc-trunk hoặc clang-9.0.0: https://godbolt.org/z/8GGT78
Lỗi với clang-trunk và -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)
Tôi hiểu rằng C ++ 20 sẽ làm cho nó chỉ có thể quá tải operator==
và trình biên dịch sẽ tự động tạo operator!=
bằng cách phủ định kết quả của operator==
. Theo tôi hiểu, điều này chỉ hoạt động miễn là loại trả về bool
.
Nguồn gốc của vấn đề là trong Eigen chúng ta khai báo một tập hợp các toán ==
, !=
, <
, ... giữa Array
các đối tượng hoặc Array
và vô hướng, mà trở lại (một biểu hiện của) một mảng của bool
(mà sau đó có thể được truy cập yếu tố khôn ngoan, hoặc sử dụng khác ). Ví dụ,
#include <Eigen/Core>
int main()
{
Eigen::ArrayXd a(10);
a.setRandom();
return (a != 0.0).any();
}
Ngược lại với ví dụ của tôi ở trên, điều này thậm chí thất bại với gcc-trunk: https://godbolt.org/z/RWktKs . Tôi chưa quản lý để giảm điều này thành một ví dụ không phải Eigen, thất bại ở cả clang-trunk và gcc-trunk (ví dụ ở trên cùng là khá đơn giản).
Báo cáo vấn đề liên quan: https://gitlab.com/libeigen/eigen/issues/1833
Câu hỏi thực tế của tôi: Đây thực sự là một thay đổi đột phá trong C ++ 20 (và có khả năng làm quá tải các toán tử so sánh để trả về các đối tượng Meta) hay không, hay nhiều khả năng là hồi quy trong clang / gcc?