As pointed out by Michael Park, adding perfect forwarding constructors can be tricky if we do not want to end up in the wrong constructor.
Currently I have a class A
which uses a perfect forwarding constructor, and because of that, I need to declare explicitly the 4 constructors: A&
, const A&
, A&&
and const A&&
:
class A
{
public:
template<typename T> A(T&&);
A(A&);
A(const A&);
A(A&&);
A(const A&&);
};
I would like to forbid the usage of the const reference rvalue constructor, so I’m considering deleting it:
class A
{
public:
template<typename T> A(T&&);
A(A&);
A(const A&);
A(A&&);
A(const A&&) = delete;
};
It looks like it works so far. But I’m just looking at a practical sample, I’d like a better confirmation, e.g. from the C++ standard.
Is it possible that the perfect forwarding constructor will take over the deleted constructor? After all, the universal reference T&&
is compatible with const A&&
.
Perfect-forwarding constructors are typically better matches for non-const lvalues.
Is it possible that the perfect forwarding constructor will take over the deleted constructor?
No. A(const A&&)
is a perfect match and it is explicitly deleted, so, if we try to construct an A
from a const lvalue reference, a compile-time error is emmited.
Yet you may do something like this
template<typename T, typename = typename std::enable_if<!std::is_same_v<A&&, T>> A(T&&);
as well.
P.S. It's a good practice to mark your constructors explicit
(especially when type deduction occurs).