Title
Problem with std::identity and reference-to-temporaries
Status
c++11
Section
[forward]
Submitter
Alisdair Meredith

Created on 2008-12-11.00:00:00 last changed 161 months ago

Messages

Date: 2010-10-21.18:28:33

Proposed resolution:

Strike from [utility]:

template <class T> struct identity;

Remove from [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

Date: 2010-10-21.18:28:33

[ 2009-10 Santa Cruz: ]

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

Date: 2009-07-30.00:00:00

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

Date: 2009-07-20.00:00:00

[ 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! ;-)

Date: 2009-07-20.00:00:00

[ 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.

Date: 2009-05-23.00:00:00

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

Date: 2010-10-21.18:28:33

[ 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.

Date: 2008-12-11.00:00:00

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)!

History
Date User Action Args
2011-08-23 20:07:26adminsetstatus: wp -> c++11
2010-10-21 18:28:33adminsetmessages: + msg4468
2010-10-21 18:28:33adminsetmessages: + msg4467
2010-10-21 18:28:33adminsetmessages: + msg4466
2010-10-21 18:28:33adminsetmessages: + msg4465
2010-10-21 18:28:33adminsetmessages: + msg4464
2010-10-21 18:28:33adminsetmessages: + msg4463
2010-10-21 18:28:33adminsetmessages: + msg4462
2008-12-11 00:00:00admincreate