Я понимаю, что компилятор делает copy-elision в коде ниже, поскольку конструкторы копирования и перемещения не вызываются в так называемом copy-initialization
, выполненном в main()
. См. live example.Выполняя copy-elision, компилятор не рассматривает конструктор копирования в разрешении перегрузки, когда конструктор перемещения удаляется. Зачем?
#include <iostream>
struct S {
S() = default;
S(const S&) { std::cout << "copy ctor" << '\n'; }
S(S&&) { std::cout << "move ctor" << '\n'; }
};
int main() {
S s = S();
}
Но я не могу понять, почему код не компилируется, когда я удаляю конструктор перемещения, как показано ниже:
#include <iostream>
struct S {
S() = default;
S(const S&) { std::cout << "copy ctor" << '\n'; }
S(S&&) = delete;
};
int main() {
S s = S();
}
Я не могу найти что-либо в §12.8/32 (N4140) что в данном случае может быть запрещено использовать конструктор копирования . Это предложение мое внимание привлекла в §12.8/32, который, кажется, указывает, что конструктор копирования должен быть рассмотрен в разрешении перегрузки:
Если первое разрешение перегрузки не может или не была выполнена, или если Тип первого параметра выбранного конструктора не является ссылкой на тип значения , относящимся к типу объекта (возможно, cv-qualified), . Реализация перегрузки выполняется снова, рассматривая объект как lvalue.
Редактировать
От одного из комментариев T.C. ниже, я понимаю, что, когда объект, подлежащий копированию, обозначен RValue, компилятор, согласно §12.8/32, не делает рассмотрите конструктор-копию в качестве кандидата на копию, хотя копия будет отодвинута в любом случае. То есть конечным результатом будет построение объекта s
со стандартным конструктором. Вместо этого в этой ситуации стандарт обязывает (где?) Код плохого формирования. Если мое понимание этой схемы совершенно неверно, это не имеет для меня никакого смысла.
Разрешение перегрузки не прерывается при обнаружении удаленной функции. Удаленные функции не являются * несуществующими *, они в некотором смысле * не удалены *. Они просто * незаконны для вызова * (их можно вызвать, и если вы это сделаете, это ошибка). – dyp
И в любом случае эта цитата из 12.8/32 не применяется. –
@ T.C. ___ Почему нет? –