Предотвращает ли деструктор базового класса создание конструктора перемещения

У меня есть класс, в котором VS 2015 не генерировал перемещение ctor, а теперь VS 2015 Update 1 генерирует его, это вызывает проблему двоичной совместимости, не уверен, какая версия делает правильно.

// MyLib
struct Shared
{
   virtual ~Shared(){}
}

struct Callback : public Shared
{
    virtual void response() = 0;
}

// App
struct CallbackI : public Callback
{
   virtual void response(){}
}

Когда я создаю MyLib с VS 2015 и приложением с VS 2015, обновление 1 связывает приложение со сбоем из-за отсутствующего символа, ссылающегося на оператор присваивания перемещения для базового класса обратного вызова.

Мне кажется, что VS 2015 не генерирует эти операторы, а VS 2015 Update 1 — да, но какая версия компилятора здесь?


person José    schedule 15.01.2016    source источник
comment
См. stackoverflow.com/a/33057705/1348273.   -  person Lingxi    schedule 15.01.2016


Ответы (1)


VS 2015 Update 1 делает правильную вещь (и на самом деле первая версия VS, которая реализует весь С++ 11)

Из стандарта:

§12.8 Копирование и перемещение объектов класса

Если определение класса X явно не объявляет конструктор перемещения, он будет неявно объявлен как заданный по умолчанию тогда и только тогда, когда

  • X не имеет объявленного пользователем конструктора копирования,
  • X не имеет объявленного пользователем оператора присваивания копии,
  • X не имеет объявленного пользователем оператора присваивания перемещения,
  • X не имеет деструктора, объявленного пользователем, и
  • конструктор перемещения не будет неявно определен как удаленный.

Созданный пользователем деструктор в Shared неявно помечает конструктор перемещения как удаленный. Когда вы позволяете компилятору сгенерировать его, компилятор также может сгенерировать оператор присваивания перемещения.

struct Shared
{
   virtual ~Shared() = default;
}

По соображениям производительности также лучше объявлять пустые виртуальные деструкторы таким образом, потому что это гарантирует встраивание компилятором.

person jupp0r    schedule 15.01.2016
comment
Насколько я понимаю, Shared, имеющий определяемый пользователем деструктор, предотвращает создание назначения перемещения и конструкторов перемещения, поэтому у производных типов его не будет. - person José; 15.01.2016
comment
другими словами, T имеет прямой или виртуальный базовый класс, который не может быть назначен перемещением (имеет удаленный, недоступный или неоднозначный оператор присваивания перемещения); en.cppreference.com/w/cpp/language/move_assignment - person José; 15.01.2016
comment
IMO vs 2015 Update 1 неверен, поскольку определяемый пользователем деструктор в Shared должен предотвращать создание оператора присваивания перемещения, и это должно повлиять на производный класс обратного вызова, поскольку он имеет виртуальный базовый класс, в котором есть удаленный оператор присваивания перемещения. - person José; 15.01.2016