Это касается разрешения проблемы C ++ http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1402 . Резюме:
template<typename T> struct wrap { wrap() = default; wrap(wrap&&) = default; wrap(const wrap&) = default; T t; }; struct S { S(){} S(const S&){} S(S&&){} }; typedef wrap<const S> W; // Error, defaulted move constructor of "wrap<const S>" is deleted! W get() { return W(); }
(Проблема заключается в том, что мы получаем ошибку для этого фрагмента, хотя компилятор может просто использовать конструктор копирования «S», как это происходит, когда пользователь явно записывает конструктор перемещения «wrap». Проблема была решена в игнорировать удаленные конструкторы перемещения (и операторы присваивания) во время разрешений перегрузки, следовательно, при необходимости используйте выше конструктор копирования.)
Когда разрешение был составлен следующий комментарий об этой резолюции:
Нет дополнительных ограничений для неявных / дефолтных операций перемещения относительно копирования. Это означает, что назначение перемещения в виртуальной базе опасно (и компиляторы, вероятно, должны предупреждать) […] Но мы решили в Батавии, что не собираемся сохранять весь код C ++ 03 от неявных операций перемещения, и я думаю, Это разрешение обеспечивает значительные преимущества в производительности.
Кто-нибудь может, пожалуйста, описать, какова проблема с виртуальными базовыми операторами перемещения?
Рассматривать:
#include <iostream>
struct A
{
A() = default;
A(const A&) = default;
A(A&&) = default;
A& operator=(const A&) {std::cout << "operator=(const A&)\n"; return *this;}
A& operator=(A&&) {std::cout << "operator=(A&&)\n"; return *this;}
};
struct B
: virtual public A
{
};
struct C
: virtual public A
{
};
struct D
: public B,
public C
{
};
int
main()
{
D d1, d2;
d1 = std::move(d2);
}
Я считаю, что эта программа должна выводить:
operator=(A&&)
operator=(A&&)
Для меня это на самом деле выводит:
operator=(const A&)
operator=(const A&)
Но я думаю, что это просто лягушка (скомпилированная с -std = c ++ 1y). Если я прав насчет того, каким должен быть вывод, тогда опасность состоит в том, что оператор присваивания перемещения вызывается дважды. Это безопасно (хотя и потенциально дорого) для оператора назначения копирования, но не для оператора назначения перемещения.
Других решений пока нет …