Can a copy constructor have a non-const lvalue parameter?

The answer to the question in the title is: yes, the copy-constructor can have a non-const argument. From the C++20 draft

11.4.4.2 Copy/move constructors [class.copy.ctor]

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


The problem is that the add member function returns an rvalue expression of type Complex and you're trying to bind a non-const lvalue reference Complex& to that rvalue.

You can solve this error by replacing Complex(Complex &c) with:

Complex(const Complex &c) //const added here

Note the const added in the above statement. Now, the parameter of the copy constructor is a reference to const Complex which can be bound to an rvalue.