Когда я возился с copy elision, я столкнулся со странным поведением:
class Obj {
public:
Obj() = default;
Obj(Obj&&) = delete;
Obj(const Obj&) { std::cout << "Copy" << std::endl; }
};
Obj f1() {
Obj o;
return o; // error C2280: move constructor is deleted
}
Obj f2() {
Obj o;
return Obj(o); // this however works fine
}
int main() {
Obj p = f1();
Obj q = f2();
return 0;
}
GCC и Clang принимают этот код и могут использовать исключение копирования в обоих случаях.
В f1()
MSVC жалуется, что не может вернуть o
, потому что конструктор перемещения Obj
удален. Однако я ожидал, что он сможет использовать конструктор копирования. Это ошибка в MSVC или это желаемое поведение (которое я не понимаю) и GCC / Clang слишком снисходительны?
Если я предоставлю конструктор перемещения, MSVC сможет исключить перемещение при компиляции как Release.
Интересно, что MSVC умеет компилировать f2()
. Насколько я понимаю, это связано с обязательным исключением копии, когда возвращается результат вызова конструктора. Однако кажется нелогичным, что я могу вернуть o
по значению, только если скопирую его вручную.
Я знаю, что эта ситуация может не иметь отношения к практическому использованию, поскольку копируемые объекты обычно также являются подвижными, но меня интересует лежащая в основе механика.
Вот онлайн-пример для тестирования: https://godbolt.org/z/sznds7
delete
d участвуют в разрешении перегрузки, похоже, существует исключение для специальных функций-членов, где они явно игнорируются. Мне кажется, это ошибка MSVC. - person cigien   schedule 28.02.2021= default
) ... - person davidbak   schedule 28.02.2021=delete
. - person cigien   schedule 28.02.2021struct B
- это= default
, но он определен как удаленный, потому чтоstruct B
содержит член, который является структурой, которая имеет удаленный (= delete
) конструктор перемещения ... - person davidbak   schedule 28.02.2021