Overloading on Forwarding Reference

suggest change

You must be very careful when providing a forwarding reference overload as it may match too well:

struct A {
    A() = default;           // #1
    A(A const& ) = default;  // #2

    template <class T>
    A(T&& );                 // #3
};

The intent here was that A is copyable, and that we have this other constructor that might initialize some other member. However:

A a;     // calls #1
A b(a);  // calls #3!

There are two viable matches for the construction call:

A(A const& ); // #2
A(A& );       // #3, with T = A&

Both are Exact Matches, but #3 takes a reference to a less cv-qualified object than #2 does, so it has the better standard conversion sequence and is the best viable function.

The solution here is to always constrain these constructors (e.g. using SFINAE):

template <class T,
    class = std::enable_if_t<!std::is_convertible<std::decay_t<T>*, A*>::value>
    >
A(T&& );

The type trait here is to exclude any A or class publicly and unambiguously derived from A from consideration, which would make this constructor ill-formed in the example described earlier (and hence removed from the overload set). As a result, the copy constructor is invoked - which is what we wanted.

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:


Overload resolution:
* Overloading on Forwarding Reference

Table Of Contents
8 Arrays
11 Loops
39 Streams
51 Unions
56 Lambdas
60 SFINAE
62 RAII
67 Sorting
72 Overload resolution
84 RTTI
87 Scopes
104 Profiling
107 Recursion
117 Iteration
125 Alignment
134 Semaphore
136 Debugging
139 Mutexes
142 decltype