Как автоконструкторы, удаленные пользователем, влияют на неявное создание конструкторов копирования? Например:
struct Foo {
Foo(X) = delete;
auto operator=(X) = delete;
};
int main() {
Foo a;
Foo b(a);
b = a;
}
В приведенной выше структуре, если X равно auto
, const auto&
или const auto&&
, компилятор по-прежнему генерирует конструктор копирования и оператор присваивания копии, и, следовательно, код компилируется и выполняется полностью нормально.
Но если X равно auto&
или auto&&
, то компилятор не будет генерировать конструктор копирования и оператор присваивания копии, и я получаю сообщение об ошибке «использование удаленной функции».
Я пробовал в GCC, Clang и ICC (к сожалению, MSVC все еще не поддерживает автоматические параметры), и во всех трех наблюдается одинаковое поведение. Так что, я думаю, это где-то определено в стандарте.
Какое стандартное правило определяет вышеупомянутое поведение компиляторов?
В любом случае мы можем получить минимальный воспроизводимый пример кода, с которым вы хотите работать, но не работает? Скорее всего, вы сталкиваетесь со случаем, когда auto&
предпочтительнее, потому что вы пытаетесь скопировать неконстантное lvalue.
Кстати, msvc поддерживает автоматические параметры, но только с С++ 20 (как и должно быть) godbolt.org/z/Gnjr7sPse
@NathanOliver извините, я обновил вопрос с минимальным воспроизводимым примером.
В вашем примере вы передаете не-const
lvalue при построении b
(как догадался @NathanOliver). auto&
и auto&&
(=> Foo&
) лучше совпадают, чем const Foo&
, поскольку не требуют преобразования.
auto
в параметре функции означает то же самое, что и замена его параметром шаблона.
Так, например.
Foo(auto&) = delete;
такой же как
template <typename T>
Foo(T&) = delete;
Шаблонные конструкторы никогда не являются конструкторами копирования/перемещения, а шаблонные операторы присваивания никогда не являются операторами присваивания копирования/перемещения.
Таким образом, они вообще не влияют на генерацию неявных конструкторов копирования/перемещения/операторов присваивания. Независимо от того, используете ли вы auto
, const auto&
, auto&
, const auto&&
или auto&&
. Неявный конструктор копирования и перемещения и операторы присваивания по-прежнему будут генерироваться.
Однако объявленные пользователем шаблонные перегрузки по-прежнему участвуют в разрешении перегрузок и в определенных ситуациях могут быть выбраны вместо неявно объявленных в соответствии с обычными правилами разрешения перегрузок.
Я обновил вопрос с минимальным воспроизводимым примером. Посмотрите, не связана ли ошибка, которую я получаю, с правилами разрешения перегрузки.
@SouravKannanthaB Это так, потому что auto&
/auto&&
, выведенное из Foo&
, лучше соответствует, чем const Foo&
из неявных перегрузок для не-const
lvalue типа Foo
(a
). Для const auto&
и const auto&&
оба одинаково хороши, поэтому предпочтительнее нешаблонный. В случае только auto
существует специальное правило, согласно которому специализация шаблона конструктора, которая сама принимает один аргумент типа класса (cv-qualified), никогда не будет рассматриваться (потому что это всегда будет бесконечная рекурсия).
Конструктор, который использует
auto
(является шаблоном), никогда не является конструктором копирования или перемещения.