Topic: std::identity


Author: =3D?ISO-8859-1?Q?Daniel_Kr=3DFCgler?=3D <daniel.kruegler@googlemail.c=.om>
Date: Wed, 2 Jun 2010 13:54:30 CST
Raw View
On May 14, 11:47 pm, "Johannes Schaub (litb)" <schaub-johan...@web.de>
wrote:
> David Krauss wrote:
> > There are many uses for std::identity besides as a helper for
> > std::move. I'm surprised just now to see that it was removed between
> > N3035 and the FCD.
>
> > Can it be moved to <utility>? I imagine there's already a fair amount
> > of C++0x code out there which depends on it, and likely the popular
> > implementations haven't yet removed it so the impact is yet unknown.
>
> I would also vote to bring it back, if it's really removed. It's one of t=
he
> most basic *and* (imho) useful metafunction and it's missing? That would =
be
> odd.

I agree that the functionality of such a metafunction is both
fundamental
and useful. One of the severest problems with std::identity is due to
the
same problem as with the pre-standard hash containers that required
a renaming of the finally standardized unordered associative
containers. The original pre-standard definition of identity contains
the member function:

const T& operator()(const T&) const;

see e.g.
http://www.sgi.com/tech/stl/identity.html

and many library implementations provide this. Unfortunately this
member causes to make some important specializations ill-formed,
e.g. std::identity<void>. Removing this member again would break
code that exists since decades. My personal favorite solution
of this problem would be to add such a meta function with a
different name, e.g. identity_of. But doing this is a pure library
addition and could be done in a future C++ TR.

Greetings from Bremen,

Daniel Kr=FCgler









--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu <std-c%2B%2B@netlab.cs.rpi.edu>]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: David Krauss <potswa@gmail.com>
Date: Sun, 6 Jun 2010 20:49:53 CST
Raw View
On Jun 2, 2:54 pm, =?ISO-8859-1?Q?Daniel_Kr=FCgler?=
<daniel.krueg...@googlemail.c=.om> wrote:
> I agree that the functionality of such a metafunction is both
> fundamental
> and useful. One of the severest problems with std::identity is due to
> the
> same problem as with the pre-standard hash containers that required
> a renaming of the finally standardized unordered associative
> containers. The original pre-standard definition of identity contains
> the member function:
>
> const T& operator()(const T&) const;
>
> see e.g.http://www.sgi.com/tech/stl/identity.html
>
> and many library implementations provide this. Unfortunately this
> member causes to make some important specializations ill-formed,
> e.g. std::identity<void>. Removing this member again would break
> code that exists since decades. My personal favorite solution
> of this problem would be to add such a meta function with a
> different name, e.g. identity_of. But doing this is a pure library
> addition and could be done in a future C++ TR.

Interesting.

It sounds like std::identity<T>::operator() is attempting to do the
job of std::forward<T> (second template argument omitted). The
difference is that forward correctly handles all argument types and
doesn't apply conversion functions: it is a better identity than
identity.

Since std::forward has two template arguments, it could safely be
embedded in std::identity to produce a useful functor:

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

   template< class U > // not instantiated implicitly with class
   T &&operator() ( U &&value ) {
       return forward<T>( value ); // or just static_cast<T&&>
   }
};

Another effect, taking the address of identity::operator() would
require an extra template argument, but I doubt that happens often and
the fix is easy.


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Mon, 7 Jun 2010 02:03:20 CST
Raw View
On Jun 7, 4:49 am, David Krauss <pot...@gmail.com> wrote:
> On Jun 2, 2:54 pm, =?ISO-8859-1?Q?Daniel_Kr=FCgler?=
> <daniel.krueg...@googlemail.c=.om> wrote:
> > I agree that the functionality of such a metafunction is both
> > fundamental
> > and useful. One of the severest problems with std::identity is due to
> > the
> > same problem as with the pre-standard hash containers that required
> > a renaming of the finally standardized unordered associative
> > containers. The original pre-standard definition of identity contains
> > the member function:
>
> > const T& operator()(const T&) const;
>
> > see e.g.http://www.sgi.com/tech/stl/identity.html
>
> > and many library implementations provide this. Unfortunately this
> > member causes to make some important specializations ill-formed,
> > e.g. std::identity<void>. Removing this member again would break
> > code that exists since decades. My personal favorite solution
> > of this problem would be to add such a meta function with a
> > different name, e.g. identity_of. But doing this is a pure library
> > addition and could be done in a future C++ TR.
>
> Interesting.
>
> It sounds like std::identity<T>::operator() is attempting to do the
> job of std::forward<T> (second template argument omitted). The
> difference is that forward correctly handles all argument types and
> doesn't apply conversion functions: it is a better identity than
> identity.
>
> Since std::forward has two template arguments, it could safely be
> embedded in std::identity to produce a useful functor:
>
> template< class T >
> struct identity {
>    typedef T type;
>
>    template< class U > // not instantiated implicitly with class
>    T &&operator() ( U &&value ) {
>        return forward<T>( value ); // or just static_cast<T&&>
>    }
>
> };

This could be done, but I don't consider it as the right solution.

First, the original (pre-standard) meaning of identity is that
of an unary function object with the following definition:

template <class T> struct identity : unary_function<T,T> {
 const T& operator()(const T& x) const {
   return x;
 }
};

This is a consistent definition that fits well into the series of
function objects defined in sub-clause [function.objects]
describing the contents of header <functional>. Notice that
all these function objects already require the type T to satisfy
the ReferentType requirement from the short but nice concept
era of C++0x, so it doesn't seem astonishing that cv void
won't produce a meaningful specialization of this class
template.

Now, when std::forward was introduced, a class template
named identity was added (in n2284 by accepting the
suggested wording of

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1856.html

) to the <utility> header with the definition:

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

as a helper type to solve a syntactic constraint problem that
a user of std::forward should be enforced to provide the
template parameter T explicitly:

template <class T> T&& forward(typename identity<T>::type&& t);

Thus, identity was only introduced to solve a particular syntactic
problem, but the later evolution of this function template
demonstrated, that proper standardese is (and should be) sufficient
to specify std::forward sufficiently without need of a helper type.

To some extend it could have been said that std::identity should
not have been added (at least not with this name), because the
reason to add it was like that of the auto_ptr_ref, namely to ensure
that a requirement was expressed by code instead of by wording
(Note that std::auto_ptr_ref's state has recently been changed to
be "for exposition only").

If we now compare the definition of std::identity from pre-standard
libraries with that from n1856 we recognize that both are intended
for completely different things: According to SGI, std::identity is a
function object, according to n1856 it is a transformation trait and
should better have better been added to the <type_traits> header.

IMO both view points of identity are completely orthogonal and should
be separated, therefore my suggestion to use a different name for
an identity transformation trait.

> Another effect, taking the address of identity::operator() would
> require an extra template argument, but I doubt that happens often and
> the fix is easy.

Sure, but IMO your revised definition of identity has two problems:

1) It deviates from the current way of defining the standard function
objects from <functional>.

2) It does not really ensure that the mapping is a T -> T mapping.
In fact, std::forward allows some T -> U mappings, where T and
U are different (e.g. when U is a base class of T).

Greetings from Bremen,

Daniel Kr   gler


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: David Krauss <potswa@gmail.com>
Date: Mon, 7 Jun 2010 20:16:51 CST
Raw View
On Jun 2, 2:54 pm, =?ISO-8859-1?Q?Daniel_Kr=FCgler?=
<daniel.krueg...@googlemail.c=.om> wrote:
> and useful. One of the severest problems with std::identity is due to
> the
> same problem as with the pre-standard hash containers that required
> a renaming of the finally standardized unordered associative
> containers. The original pre-standard definition of identity contains
> the member function:
>
> const T& operator()(const T&) const;
>
> see e.g.http://www.sgi.com/tech/stl/identity.html
>
> and many library implementations provide this. Unfortunately this
> member causes to make some important specializations ill-formed,
> e.g. std::identity<void>. Removing this member again would break
> code that exists since decades. My personal favorite solution
> of this problem would be to add such a meta function with a
> different name, e.g. identity_of. But doing this is a pure library
> addition and could be done in a future C++ TR.

I replied to this several days ago, but it was apparently lost in a
system glitch... or the mods didn't like it.

[ The message included a problematic ill-formed "References:" header;
I've now edited it manually -- mod/jad ]

The const-reference implementation of identity is exactly what
std::forward was introduced to improve.

Furthermore, std::forward is a template of two arguments, so if it
were embedded in class std::identity, the additional argument would
prevent deleterious immediate instantiation.

Therefore, I suggest

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

   template< typename U  >
   T &&operator() ( U &&value )
       { return forward< T >( value ); }
};


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: David Krauss <potswa@gmail.com>
Date: Thu, 13 May 2010 12:04:59 CST
Raw View
There are many uses for std::identity besides as a helper for
std::move. I'm surprised just now to see that it was removed between
N3035 and the FCD.

Can it be moved to <utility>? I imagine there's already a fair amount
of C++0x code out there which depends on it, and likely the popular
implementations haven't yet removed it so the impact is yet unknown.

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Fri, 14 May 2010 15:47:24 CST
Raw View
David Krauss wrote:

> There are many uses for std::identity besides as a helper for
> std::move. I'm surprised just now to see that it was removed between
> N3035 and the FCD.
>
> Can it be moved to <utility>? I imagine there's already a fair amount
> of C++0x code out there which depends on it, and likely the popular
> implementations haven't yet removed it so the impact is yet unknown.
>

I would also vote to bring it back, if it's really removed. It's one of the
most basic *and* (imho) useful metafunction and it's missing? That would be
odd.

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]