Search code examples
c++c++11constructorperfect-forwardingforwarding-reference

Perfect forwarding constructor and deleted constructors


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&&.


Solution

  • 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).