On 10/15/2022 3:42 PM, Marcel Mueller wrote:
>
> Why? I thought reference_wrapper is intended to be used with arrays.
> Or is this one of the blemishes of C++11 that has been fixed in later
> versions?
`std::reference_wrapper<>` is not a reference. It will not extend the
lifetime of temporaries the same way a true reference does. How did you
expect your code to work?
To prevent you from making such erroneous assumptions and running into
subsequent problems, the class specification has a dedicated requirement
(see
https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/reference_wrapper):
---
template< class U >
constexpr reference_wrapper( U&& x ) noexcept(/*see below*/) ;
Converts x to T& as if by T& t = std::forward<U>(x), then stores a
reference to t. This overload participates in overload resolution only
if typename std::decay<U>::type is not the same type as
reference_wrapper and the expression FUN(std::declval<U>()) is
well-formed, where FUN names the set of imaginary functions
void FUN(T&) noexcept;
void FUN(T&&) = delete;
---
That `FUN` part is the one intended to reject binding to non-lvalues.
Which is exactly what happens in your case.
> If I do the same with a simple custom reference wrapper it works:
>
> template <typename T>
> struct reference
> { T& Ref;
> constexpr reference(T& ref) : Ref(ref) { }
> constexpr operator T&() const { return Ref; }
> };
No, it doesn't. It merely "compiles". But the temporaries get destroyed
almost immediately and you end up with a bunch of dangling references.
--
Best regards,
Andrey