Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why auto cannot be used to define an implicitly deleted constructor

Tags:

c++

gcc

I have this small snippet (compiled with g++) where I have defined a move constructor:

#include <iostream>
using namespace std;

class A {
public:
  A() = delete;
  A(int value) : value(value) {}
  void operator=(const auto &other) = delete;
  ~A() { cout << "Destructor called..." << endl; }

  A(const auto &other) {
    cout << "Copy constructor called..." << endl;
    value = other.value;
  }

  A(const A &&other) {
    cout << "Move constructor called..." << endl;
    value = other.value;
  }

private:
  int value;
};

int main() {
  A p1(2);
  A p2(p1);

  return 0;
}

The problem is that I'm getting main.cpp:27:10: error: use of deleted function 'constexpr A::A(const A&)'

From what I understand, there is a compiler convention to implicitly delete any copy operations when a move constructor is defined. They will have to be explicitly defined if the user needs them.

However, I attempt to define a copy constructor using auto as the argument. If the constructor signature is A(const A &other) the program runs fine.

Since auto will be resolved to A, what is the reason for which the compiler still deems that particular constructor deleted?

like image 414
user2565010 Avatar asked Oct 22 '25 06:10

user2565010


1 Answers

Since auto will be resolved to A, what is the reason for which the compiler still deems that particular constructor deleted?

Because A::A(const auto &) cannot be a copy constructor as when auto is used in the parameter of a function, that function declaration/definition is actually for a function template. Basically A::A(const auto&) is a templated constructor. But according to class.copy.ctor a templated constructor cannot be a copy constructor.

A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments ([dcl.fct.default]).

(emphasis mine)


And since you've defined a move constructor A::A(const A&&), the synthesized copy ctor A::A(const A&) is implicitly deleted. But note that the implicitly deleted copy ctor A::A(const A&) takes part in overload resolution and is still a better match than the templated constructor A::A(const auto&). Thus, the copy ctor is chosen but since it is deleted(implicitly) we get the mentioned error.


like image 142
Anoop Rana Avatar answered Oct 23 '25 20:10

Anoop Rana