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

Это касается разрешения проблемы 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 от неявных операций перемещения, и я думаю, Это разрешение обеспечивает значительные преимущества в производительности.

Кто-нибудь может, пожалуйста, описать, какова проблема с виртуальными базовыми операторами перемещения?

4

Решение

Рассматривать:

#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). Если я прав насчет того, каким должен быть вывод, тогда опасность состоит в том, что оператор присваивания перемещения вызывается дважды. Это безопасно (хотя и потенциально дорого) для оператора назначения копирования, но не для оператора назначения перемещения.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]