Стандарт C ++ 17 гласит:
15.8.2 Оператор назначения копирования / перемещения [class.copy.assign]
...
10 Оператор назначения копирования / перемещения для класса X, который по умолчанию и не определен как удаленный, неявно определяется, когда используется odr (6.2) (например, когдаон выбирается с помощью разрешения перегрузки для назначения объекту своего типа (или когда он явно установлен по умолчанию после его первого объявления). Неявно определенный оператор присваивания копирования / перемещения имеет вид constexpr
, если
(10.1) - X
является литеральным типом, а
(10.2) - оператор присваивания, выбранный для копирования /Переместить каждый подобъект прямого базового класса - это функция constexpr
, а
(10.3) - для каждого не статического члена данных X
, который имеет тип класса (или его массив), оператор присваивания, выбранный для копирования /переместить этот элемент является функцией constexpr
.
Оператор копирования-назначения удовлетворяет вышеуказанным требованиям в двух случаях.В первом случае у нас есть не-литеральный тип из-за нетривиального деструктора.
Поэтому я считаю, что Clang неправильно отклоняет код во втором случае.
Существуетошибка, поданная в Clang под названием: Деструктор по умолчанию не позволяет использовать constexpr для оператора копирования / перемещения , который показывает те же симптомы, что и код в OP.
Комментарии из состояния отчета об ошибке:
Когда по умолчанию деструктор закомментирован (т.е. не объявлен пользователем), ошибки перестают существовать.
и
Проблема такжепропадает, если вы объявите деструктор перед оператором присваивания копии.
Это верно и для кода в вопросе.
Как указывает @YSC, здесь есть еще одна важная цитатаis: [dcl.fct.def.default] / 3 , в котором говорится:
Явно заданная по умолчанию функция, которая не определена как удаленная, может быть объявлена constexpr
или consteval
только если бы это было неявно деОбозначается как constexpr
.Если функция явно установлена по умолчанию в своем первом объявлении, она неявно считается равной constexpr
, если неявное объявление будет.