[cfe-dev] Broken type deduction for pair of reference_wrappers?

James Dennett james.dennett at gmail.com
Thu Aug 9 20:02:17 PDT 2012


On Thu, Aug 9, 2012 at 7:16 PM, Michael Price
<michael.b.price.dev at gmail.com> wrote:
> On Thu, Aug 9, 2012 at 5:48 PM, Richard Smith <richard at metafoo.co.uk> wrote:
>>
>> On Wed, Aug 8, 2012 at 7:41 PM, Michael Price
>> <michael.b.price.dev at gmail.com> wrote:
>>>
>>> Given two objects, one and two that are references to some pure virtual
>>> type MyType, the following code compiles fine:
>>>
>>>     std::pair<std::reference_wrapper<MyType>,std::reference_wrapper<
>>> MyType >> mypair = std::make_pair(std::ref(one), std::ref(two));
>>>     std::swap(mypair.first, mypair.second);
>>>
>>> But if I replace the declaration of the pair object type with 'auto' as
>>> in:
>>>
>>>     auto mypair = std::make_pair(std::ref(one), std::ref(two));
>>
>>
>> mypair's type is std::pair<MyType&, MyType&>. See the make_pair
>> specification:
>>
>> template <class T1, class T2> pair<V1, V2> make_pair(T1&& x, T2&& y);
>>
>> Returns: pair<V1, V2>(std::forward<T1>(x), std::forward<T2>(y));
>> where V1 and V2 are determined as follows: Let Ui be decay<Ti>::type for
>> each Ti. Then each Vi is
>> X& if Ui equals reference_wrapper<X>, otherwise Vi is Ui.
>>
>
> So, I guess that std::pair<MyType&, MyType&> is assignable to
> std::pair<std::reference_wrapper<MyType&>, std::reference_wrapper<MyType&>>
> then?

Given that reference_wrapper<T> is implicitly constructible from T&
(though not T&&), yes.

>>
>> Then...
>>
>>>
>>> I get the following errors with std::swap:
>>>
>>> GameController.cpp:43:9: error: no matching function for call to 'swap'
>>>         std::swap(mypair.first, mypair.second);
>>>         ^~~~~~~~~
>>> /usr/include/c++/v1/type_traits:2902:5: note: candidate template ignored:
>>> disabled by 'enable_if' [with _Tp = MyType]
>>>     is_move_constructible<_Tp>::value &&
>>>     ^
>>
>>
>> your values can't be swapped, because MyType is not move constructible,
>> because it's an abstract class type. The specification for 'swap' says:
>>
>> Requires: Type T shall be MoveConstructible (Table 20) and MoveAssignable
>> (Table 22).
>>
> Why does it compile (and it does in fact appear to execute correctly) if
> mypair is a pair of reference_wrappers then?

Because reference_wrapper is CopyConstructible and CopyAssignable
(hence MoveConstructible and MoveAssignable), which is why it's a good
match for what std::pair needs.

> I don't think that
> reference_wrapper is MoveConstrucible and MoveAssignable.

Why not?

-- James



More information about the cfe-dev mailing list