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

James Dennett james.dennett at gmail.com
Fri Aug 10 13:10:31 PDT 2012


On Thu, Aug 9, 2012 at 11:28 PM, James Dennett <james.dennett at gmail.com> wrote:
> On Thu, Aug 9, 2012 at 10:35 PM, Michael Price
> <michael.b.price.dev at gmail.com> wrote:
>>
>> On Thu, Aug 9, 2012 at 11:48 PM, James Dennett <james.dennett at gmail.com>
>> wrote:
>>>
>>> On Thu, Aug 9, 2012 at 9:41 PM, Michael Price
>>> <michael.b.price.dev at gmail.com> wrote:
>>> > On Thu, Aug 9, 2012 at 10:02 PM, James Dennett <james.dennett at gmail.com>
>>> > wrote:
>>> >>
>>> >> 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:
>>>
>> <SNIP>
>>>
>>> >> >>
>>> >> >> 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.
>
> In hindsight: The standard makes this claim, but I think it's wrong.

But I was wrong about being wrong.  Which still means I was wrong, but
about the wrong thing.

>>> >> > I don't think that
>>> >> > reference_wrapper is MoveConstrucible and MoveAssignable.
>>> >>
>>> >> Why not?
>>> >
>>> > The following web page mentions CopyConstructible and CopyAssignable,
>>> > but
>>> > not the move equivalents (granted, it is not authoritative).
>>> > http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper
>>> >
>>> > Why would copyable imply movable? You can definitely have types that are
>>> > copyable but not movable as they can be deleted independently.
>>>
>>> The standard specifies the requirements for CopyConstructible and
>>> CopyAssignable as refinements of  MoveConstructible and MoveAssignable
>>> respectively (see tables 20-23).
>>>
>> 20.8.3 Class template reference_wrapper [refwrap]
>>
>> namespace std {
>>   template <class T> class reference_wrapper {
>>   public :
>> ...
>>     // construct/copy/destroy
>>     reference_wrapper(T&) noexcept;
>>     reference_wrapper(T&&) = delete; // do not bind to temporary objects
>>     reference_wrapper(const reference_wrapper<T>& x) noexcept;
>>     // assignment
>>     reference_wrapper& operator=(const reference_wrapper<T>& x) noexcept;
>> ...
>>   };
>> }
>>
>> Clearly that thing cannot be move constructed.  Maybe we are talking past
>> each other at this point.  I feel that I still don't quite understand how a
>> type could be considered MoveConstructible, yet have a deleted move
>> constructor, but I'm willing to chalk that up to language-lawyer-ese.

As others have flagged, it's only the constructor from T&& to
reference_wrapper<T> that's deleted, not the move constructor
reference_wrapper<T>::reference_wrapper(reference_wrapper<T>&&).
reference_wrapper<T> can be copied, including from temporaries, and
all is good.



More information about the cfe-dev mailing list