Поддержка C ++ 20 в GCC все еще экспериментальная, поэтому пока она действительно поддерживает трехсторонний оператор, ваш static_assert
не работает, потому что другие компиляторы автоматически определяют оператор <=
из <=>
, в то время как GCC кажется более педантичным в своей интерпретации стандарта, и поскольку у вас нет оператора <=
напрямую, компилятор выдает ошибку времени компиляции, потому что он не может найти оператор <=
.
Если добавить оператор <=
, код работает, например:
struct S{
constexpr operator int() const { return 0; }
constexpr auto operator<=>(S) const { return *this; }
constexpr bool operator<=(S) { return true; }
};
static_assert(S{} <= S{});
Кроме того, если вы измените свое assert на трехсторонний оператор, тест не пройдет на всех компиляторах, например:
struct S{
constexpr operator int() const { return 0; }
constexpr auto operator<=>(S) const { return *this; }
};
static_assert(S{} <=> S{});
Кроме того, поскольку ожидается, что трехсторонний оператор по существу вернет отрицательное, нулевое или положительное значение (на самом деле возвращает порядок), возврат *this
, скорее всего, преобразует значение во что-то, что Clang и MSVC интерпретируют как значение true
для утверждения, в то время как GCC может преобразовывать его в значение false
, и, таким образом, утверждение не выполняется.
Если вы измените тип возвращаемого значения на любое отрицательное значение (даже -0
) или нулевое значение, утверждение будет передано всем компиляторам, кроме того, если вы измените значение на любое положительное значение выше 0, утверждение не будет выполнено на всех компиляторах.
Вы можете изменить трехсторонний оператор, чтобы преобразовать *this
в int
, который вызовет operator int
и вернет 0, что затем вызовет передачу утверждения, например:
constexpr auto operator<=>(S) const { return static_cast<int>(*this); }
Итак, чтобы ответить прямо:
Какой компилятор правильный?
По моему опыту работы с GCC, он имеет тенденцию очень педантично интерпретировать язык и проявлять осторожность, когда дело доходит до спецификации языка, которая может быть двусмысленной перед лицом странного фрагмента кода (например, вашего ).
С этой целью другие компиляторы могут быть слишком свободными в интерпретации языка или GCC может быть слишком строгим в данном конкретном случае.
В любом случае, даже если этот код бесполезен, любой, кто сталкивается с чем-то вроде этого и нацелен на все 3 компилятора, вероятно, должен попытаться быть максимально педантичным с этим типом кода, хотя это обязательно может нарушить цель кода в этот случай, к сожалению.
person
txtechhelp
schedule
17.03.2021
*this
из<=>
- это проблема. Кстати, странно это делать, могу я спросить, почему вы это написали? - person cigien   schedule 17.03.2021S{} <= 0
компилируется нормально? Или он пытается рекурсивно вызватьoperator <=>
и терпит неудачу, потому что второй тип операндаint
не соответствуетS
? - person Ben Voigt   schedule 17.03.2021S{} <= 0
отлично компилируется. - person cigien   schedule 17.03.2021