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

Michael Price michael.b.price.dev at gmail.com
Thu Aug 9 21:41:25 PDT 2012


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:
> >>
> >> 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?
>
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.

>
> -- James
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20120809/cdca3a22/attachment.html>


More information about the cfe-dev mailing list