3

How does user deleted auto constructors affect implicit generation of copy constructors? For eg:

struct Foo {
    Foo(X) = delete;
    auto operator=(X) = delete;
};

int main() {
    Foo a;
    Foo b(a);
    b = a;
}

In the above struct, if X is auto, const auto& or const auto&& then the compiler still generate the copy constructor and copy assignment operator, and hence the code is being compiled and executed completely fine.

But if X is auto& or auto&& then compiler will not generate the copy constructor and copy assignment operator, and I'm getting 'use of deleted function' error.

I have tried in GCC, Clang and ICC (unfortunately MSVC doesn't support auto parameters still), and same behavior is observed in all three. So, I guess it is somewhere defined in the standard.

Which standard rule guides the aforementioned behavior of compilers?

Sourav Kannantha B
  • 2,860
  • 1
  • 11
  • 35
  • 2
    A constructor that uses `auto` (is a template) is **never** a copy or move constructor. – NathanOliver Feb 20 '23 at 17:42
  • 3
    Any way we can get an [mre] of the code that you want to work but doesn't? Most likely you are running into a case where `auto&` is preferred because you are trying to copy a non-const lvalue. – NathanOliver Feb 20 '23 at 17:44
  • 1
    btw msvc does support auto parameters, but only with c++20 (as it should) https://godbolt.org/z/Gnjr7sPse – 463035818_is_not_an_ai Feb 20 '23 at 18:36
  • @NathanOliver sorry, I have updated the question with minimal reproducible example. – Sourav Kannantha B Feb 20 '23 at 19:50
  • 1
    In your example, you pass a non-`const` lvalue when constructing `b` (like @NathanOliver guessed). `auto&` and `auto&&` (=> `Foo&`) are better matches than `const Foo&` since it doesn't require any conversion. – Ted Lyngmo Feb 20 '23 at 20:55

1 Answers1

3

auto in a function parameter means exactly the same as replacing it with a template parameter.

So e.g.

Foo(auto&) = delete;

is the same as

template <typename T>
Foo(T&) = delete;

Templated constructors are never copy/move constructors and templated assignment operators are never copy/move assignment operators.

So they do not affect generation of implicit copy/move constructors/assignment oprators at all. No matter whether you use auto, const auto&, auto&, const auto&& or auto&&. The implicit copy and move constructor and assignment operators will still be generated.

However, the user-declared templated overloads still participate in overload resolution and may in certain situations be chosen over the implicitly-declared ones in accordance with the the normal overload resolution rules.

user17732522
  • 53,019
  • 2
  • 56
  • 105
  • I have updated the question with minimal reproducible example. See if the error I'm getting is because of overload resolution rules. – Sourav Kannantha B Feb 20 '23 at 19:52
  • 1
    @SouravKannanthaB It is, because `auto&`/`auto&&` deduced to `Foo&` is a better match than `const Foo&` from the implicit overloads for a non-`const` lvalue of type `Foo` (`a`). For `const auto&` and `const auto&&` both are equally good, so the non-template one is preferred. In the case of just `auto` there is a special rule that a constructor template specialization that would take a single argument of the (cv-qualified) class type itself will never be considered (because it would always be an infinite recursion). – user17732522 Feb 21 '23 at 06:53