Date
2017-06-28.19:32:15
Message id
9311

Content

reference_wrapper<T> has a deleted constructor taking T&& in order to prevent accidentally wrapping an rvalue (which can otherwise happen with the reference_wrapper(T&) constructor if T is a non-volatile const-qualified type). Unfortunately, a deleted constructor can still be used to form implicit conversion sequences, so the deleted T&& constructor has the (presumably unintended) effect of creating an implicit conversion sequence from a T rvalue to a reference_wrapper<T>, even though such a conversion would be ill-formed if actually used. This is visible in overload resolution:

void meow(std::reference_wrapper<int>); //#1
void meow(convertible_from_int); //#2
meow(0); // error, ambiguous; would unambiguously call #2 if #1 instead took int&

and in conditional expressions (and hence std::common_type) after core issue 1895:

std::reference_wrapper<int> purr();

auto x = true? purr() : 0; // error, ambiguous: ICS exists from int prvalue to 
                           // reference_wrapper<int> and from reference_wrapper<int> to int

using t = std::common_type_t<std::reference_wrapper<int>, int>; // error: no member 'type' because the conditional 
                                                                // expression is ill-formed

The latter in turn interferes with the use of reference_wrapper as a proxy reference type with proxy iterators.

We should ensure that there is no implicit conversion sequence from T rvalues to reference_wrapper<T>, not just that the conversion will be ill-formed when used. This can be done by using a suitably constrained constructor template taking a forwarding reference instead of the current pair of constructors taking T& and T&&.