Разве добавление конструктора перемещения нарушает двоичную совместимость?

Если я добавлю в конструктор move (или оператор переадресации) мою библиотеку, я нарушу бинарную совместимость? Может ли это дополнение каким-либо образом сломать код пользователя?

class Foo {
public:
  Foo();
  Foo(Foo const&);
  Foo& operator=(Foo const&);

// new methods:
  Foo(Foo&&);
  Foo& operator=(Foo&&);
};

Ответ 1

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

Если один компонент (например, разделяемая библиотека, .dll в Windows или .so в Linux) использует старую версию библиотеки, то он копирует все экземпляры объекта (даже rvalues) независимо от того, был ли он создан компонентом, использующим новую библиотеку (и наоборот).

До тех пор, пока семантика перемещения используется для повышения производительности, и поэтому полученные перемещенные объекты ведут себя так же, как скопированные объекты, проблем не должно быть. Единственными отличиями могут быть повышение производительности, вызванное меньшим количеством вызовов в память [de] распределения и копии (и т.д.). Если операции перемещения используются для создания другой семантики (перемещенный объект отличается от скопированного объекта), тогда все ставки отключены, но я не думаю, что кто-то сделал это специально (за исключением, возможно, для безопасности работы).

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

Ответ 2

Он определенно нарушает двоичную совместимость в одном направлении: код, скомпилированный против вашей новой библиотеки, не может работать со старым, поскольку конструктор перемещения не будет найден при связывании.

Другое направление сложнее. Как правило, это не большая проблема, но код может наблюдать, по крайней мере, присутствие нового оператора присваивания с помощью трюков SFINAE, и вы получаете программу, в которой некоторые части считают, что оператор существует, а другие - нет. Это может даже вызвать нарушения ODR, если один и тот же код скомпилирован дважды (тот же шаблонный экземпляр в разных единицах перевода). И те нарушения ODR могут снова вызвать ошибки времени соединения.