This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.

### 939. Problem with `std::identity` and reference-to-temporaries

Section: 20.2.4 [forward] Status: C++11 Submitter: Alisdair Meredith Opened: 2008-12-11 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [forward].

View all issues with C++11 status.

Discussion:

`std::identity` takes an argument of type `T const &` and returns a result of `T const &`.

Unfortunately, this signature will accept a value of type other than `T` that is convertible-to-`T`, and then return a reference to the dead temporary. The constraint in the concepts version simply protects against returning reference-to-`void`.

Solutions:

> i/ Return-by-value, potentially slicing bases and rejecting non-copyable types

> ii/ Provide an additional overload:

> >     template< typename T >
> >     template operator( U & ) = delete;

> This seems closer on intent, but moves beyond the original motivation for the operator, which is compatibility with existing (non-standard) implementations.

> iii/ Remove the `operator()` overload. This restores the original definition of the `identity`, although now effectively a type_trait rather than part of the perfect forwarding protocol.

> iv/ Remove `std::identity` completely; its original reason to exist is replaced with the `IdentityOf` concept.

My own preference is somewhere between (ii) and (iii) - although I stumbled over the issue with a specific application hoping for resolution (i)!

[ Batavia (2009-05): ]

> We dislike options i and iii, and option ii seems like overkill. If we remove it (option iv), implementers can still provide it under a different name.

> Move to Open pending wording (from Alisdair) for option iv.

[ 2009-05-23 Alisdair provided wording for option iv. ]

[ 2009-07-20 Alisdair adds: ]

> I'm not sure why this issue was not discussed at Frankfurt (or I missed the discussion) but the rationale is now fundamentally flawed. With the removal of concepts, `std::identity` again becomes an important library type so we cannot simply remove it.

> At that point, we need to pick one of the other suggested resolutions, but have no guidance at the moment.

[ 2009-07-20 Howard adds: ]

> I believe the rationale for not addressing this issue in Frankfurt was that it did not address a national body comment.

> I also believe that removal of `identity` is still a practical option as my latest reformulation of `forward`, which is due to comments suggested at Summit, no longer uses `identity`. :-)

> >     template <class T, class U,
> >         class = typename enable_if
> >                 <
> >                     !is_lvalue_reference<T>::value ||
> >                      is_lvalue_reference<T>::value &&
> >                      is_lvalue_reference<U>::value
> >                 >::type,
> >         class = typename enable_if
> >                 <
> >                     is_same<typename remove_all<T>::type,
> >                             typename remove_all<U>::type>::value
> >                 >::type>
> >     inline
> >     T&&
> >     forward(U&& t)
> >     {
> >         return static_cast<T&&>(t);

> >     }

> > [ The above code assumes acceptance of 1120 for the definition of `remove_all`. This is just to make the syntax a little more palatable. Without this trait the above is still very implementable. ]

> Paper with rationale is on the way ... really, I promise this time! ;-)

[ 2009-07-30 Daniel adds: See 823 for an alternative resolution. ]

[ 2009-10 Santa Cruz: ]

> Move to Ready. Howard will update proposed wording to reflect current draft.

Proposed resolution:

Strike from 20.2 [utility]:

>     template <class T> struct identity;

Remove from 20.2.4 [forward]:

>     template <class T> struct identity {
>       typedef T type;

>       const T& operator()(const T& x) const;
>     };

>     const T& operator()(const T& x) const;

> > -2- Returns: `x`