Can a copy constructor have a non-const lvalue parameter?
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.
Non-const copy constructor compiles fine with C++17
fun()
is a prvalue of type A
, so A a = fun();
means that a
is the result object of the function call, there is no intermediate temporary.
The text for this is in C++17 [basic.lval]/2:
The result object of a prvalue is the object initialized
by the prvalue;
It would be the same for A a = A(A(A(A(A(fun())))));
etc. - all of the prvalues have a
as their result object.
The behaviour of the return statement is in [stmt.return]/2:
the
return
statement initializes the glvalue result or prvalue result object of the (explicit or implicit) function
call by copy-initialization (11.6) from the operand.
The result object can be initialized successfully by copy-initialization from a
(the local variable of fun
) because that is a non-const lvalue and so the copy constructor taking non-const lvalue reference does bind to it.
Prior to C++17 fun()
's return value was a temporary object, and then main's a
was copy/move-constructed from the temporary, with elision being optional (but the valid constructor was required to exist).
why templated non const parameter constructor is preferred to given copy constructor
The problem is not with std::variant
. The problem is with the constructor template,
template <typename T>
A(T& t)
Such constructors are problematic because when the argument is a non-const
lvalue of type A
, this constructor is preferred over the copy constructor taking const A&
---which is usually not the intended behaviour. To prevent this, we usually constrain this constructor with SFINAE:
template <typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, A>>>
A(T& t) // or T&& t
and might consider making it explicit
as well.
We usually do not provide copy constructors taking non-const
A&
, since they are redundant next to the ones taking const A&
.
Copy constructor converts from const to non-const?
No idea what you mean. A(const A&)
is a typical copy-ctor, which has a "read-only" access to its only argument. If you pass anything const, everything is fine. If you pass anything non-const, for ctor it becomes const. A a = 1
is a conversion ctor, as you said. A other = a
is a copy ctor. What's the question?
Regarding your question's title, in C++ there's no fair way to convert const
to non-const
.
class A
{
public:
int xx;
A(const A& other)
{
cout << "A cctor" << endl;
/* do some stuff */
// other is const here - you can only call its
// const methods and read all its data members
}
A(int x) : xx(x) {} /* conversion constructor */
// at this point, x is not const, but it's a copy
// of an object you've passed here, not the object itself
// you can change x, it just doesn't matter - you
// change the copy
};
int main()
{
A a = 1; // a is not const, 1 is passed "by value", since it's primitive type
A other = a; // a is not const, other is not const, a is passed by const reference
return 0;
}
Non-const copy constructor
In your case, you probably should use the mutable
keyword.
Your object would still remain logically const because, from the user point of view, nothing has changed.
Related Topics
Memoized, Recursive Factorial Function
Drawing in a Win32 Console on C++
Const Method That Modifies *This Without Const_Cast
Convert Std::String to Qstring
Is Constexpr a "Hint" (Like Inline) or "A Binding Request" to the Compiler
Hide a C++ Code Block from Intellisense
What Is the Array Form of 'Delete'
Priority Queue with Limited Space: Looking for a Good Algorithm
Concurrent Writes in the Same Global Memory Location
Get Private Data Members for Non Intrusive Boost Serialization C++
How to Show Qsqlquerymodel in Qml
How to Embed/Link Binary Data into a Windows Module