Why does overload resolution not fall back to constructor with reference to base class when copy-constructor is deleted?

Viewed 59

As a followup question to this question:

class Base {
    public:
    virtual ~Base() {}
    virtual void func() = 0;
};

class A : public Base {
    public:
     void func() override { std::cout << this << std::endl; }
};

class B : public Base {
    private:
     Base& base;

     public:
      B(B&) = delete;
      B(Base& b) : base(b) {}
      void func() override { std::cout << &base << std::endl; }
};

int main()
{
  A a;
  B b(a);
  B c(b);

  return 0;
}

Why does overload resolution not fall back to the constructor taking a reference to the base class (B(Base& b)) when the copy constructor is deleted?

1 Answers

Because = delete is a still a definition of the constructor (it is defined as deleted). Deleted functions are still possible candidates in overload resolution, and, in this case, the copy constructor is still the most viable candidate, and it is selected. Since a deleted function is referred to, the program is ill-formed.

From the standard, [dcl.fct.def.delete]:

  1. A deleted definition of a function is a function definition whose function-body is of the form = delete ; [...] A deleted function is a function with a deleted definition or a function that is implicitly defined as deleted.
  2. A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed.

And it is pretty easy to see why a definition for B::B(B&) is more viable than B::B(Base&) for an lvalue of type B

Related