Удален неявно объявленный оператор присваивания копии - PullRequest
0 голосов
/ 08 ноября 2018

В соответствии со ссылкой C ++ на Оператор присваивания копии :

Оператор присваивания по умолчанию для класса T определяется как удаленный, если выполняется любое из следующих условий

T имеет нестатический член данных не-классового типа (или его массив), который является константой ...

Я надеялся создать случай, когда у меня был элемент данных типа const и оператор присваивания копии по умолчанию, который не был определен как удаленный. При этом я обнаружил несоответствие между clang и gcc. Рассмотрим следующий код:

struct B {
  void operator=(const B&) const {}
};

struct A {
  const B b{};
  A& operator=(const A&) = default;
};

int main() {
  A a1{}, a2{};
  a1 = a2;       //only works with clang
  B b1{}, b2{};
  b1 = b2;       //works in both
}

Когда я компилирую это с g++ -std=c++14, я получаю следующие ошибки:

In member function ‘A& A::operator=(const A&)’:
error: non-static const member ‘const B A::b’, can’t use default assignment operator
note: synthesized method ‘A& A::operator=(const A&)’ first required here

Это, однако, запятая, компилируется с clang, так как ссылка, кажется, указывает, что это должно. Я ошибаюсь? Какой компилятор правильный?

Я использую gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04) и clang version 6.0.0-1ubuntu2.

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

Кажется, что лязг прав,

Хотя еще не подтверждено, существует отчет по теме gcc и, как было указано, два правила, относящиеся к этому делу, не применяются

[class.copy.assign] / 7

(7.2) нестатический член данных типа const, не относящийся к классу (или его массив), или

[...]

(7.4) прямой нестатический член данных типа класса M (или его массив) или прямой базовый класс M, который не может быть скопирован / перемещен из-за разрешения перегрузки ([over.match]), применяемого для поиска M соответствующий оператор присваивания приводит к неоднозначности или функции, которая удалена или недоступна из оператора присваивания по умолчанию.

0 голосов
/ 08 ноября 2018

Похоже, что clang верен, раздел [class.copy.assign] p7 говорит:

Оператор присвоения по умолчанию для копирования / перемещения для класса X определяется как удалено, если X имеет:

  • (7.1) вариантный член с нетривиальным соответствующим оператором присваивания и X является объединяющим классом, или
  • (7.2) нестатический член данных типа const, не относящийся к классу (или его массив), или
  • (7.3) нестатический элемент данных ссылочного типа или
  • (7.4) прямой нестатический член данных типа класса M (или его массив) или прямой базовый класс M, который не может быть скопирован / перемещен, поскольку разрешение перегрузки ([over.match]), применяемое для поиска M соответствующий оператор присваивания, приводит к неоднозначности или функция, которая удалена или недоступна из задания по умолчанию оператор.

Оператор назначения перемещения по умолчанию, который определен как удаленный, игнорируется разрешением перегрузки ([over.match], [over.over]).

и ни один из этих случаев не имеет места.

Хотя я должен сказать, что оператор присваивания копии const , который возвращает void, кажется новым, формулировка в [class.copy.assign] p1 наверняка позволяет.

Существует открытый отчет об ошибке gcc для аналогичного случая. Субобъект Const с оператором присваивания const, но оператор в любом случае удалил с кодом следующим образом:

class bar
{
public:
    bar() {}

    bar const & operator=(bar const &) const
    {
        return *this;
    }
};

class foo
{
    bar const v;
};

int main()
{
    foo a;

    a = foo();
}

Репортер указывает на тот же раздел, что и я.

...