------------------------------ Message: 3 Date: Thu, 22 Nov 2012 11:31:05 -0800 From: "Jeffrey Lee Hellrung, Jr." <jeffrey.hellrung@gmail.com> To: boost-users@lists.boost.org Subject: Re: [Boost-users] [Range & c++0x Lambdas] Can this be done? Message-ID: <CANvXPuQmePirYFadBKRyVoQur1N8DH2c-QhwqHgZMV2MNfG_gQ@mail.gmail.com> Content-Type: text/plain; charset="iso-8859-1"
Maybe this is what you did, so I might not be suggesting something new,
but... Perhaps boost::result_of could have an extra conditional logic
branch added to it:
I don't recall the details, but I've learned that result_of has compatibility issues with old/new ways in general.  So, if the "old way" is published at all, use it (for backward compatibility, in case it is different from what decltype would detect).  This allows lamdas and other code that assumes decltype is being used, while preseving the behavior of code that explicitly publishes the type.
- If F::result_type exists, return F::result_type;
- Else:  << same as before >>
Meanwhile, for different reasons, I made a macro that abstracts the
different syntax between C++11 lambdas and Apple Block Closures. The latter
generates a suitable lambda class complete with result_of member. That
makes me think that you could have a macro that wraps a compiler-generated
lambda expression in another class that inherits the operator() etc. and
adds in the result_of typedef to simply use decltype.

Wouldn't that require defining a class at expression scope? Is that
possible?

- Jeff

Here's my docs on the matter:

   Given a macro M, at its simplest M can expand to either [=] or ^ depending on the platform,
   and then be followed by the optional lambda-declarator and compound-statement.

   However, Apple's Blocks do not have proper value semantics.  You must call a function on it before
   leaving the scope where it was defined, if it is to be used outside of that scope.  And then it needs
   to be explicitly destroyed when it is no longer needed.

   In order to use it transparently in C++, it needs to be wrapped in an object with a destructor,
   (and that wrapper can take care of the initial function call too).  But we don't want to have to inject
   anything _after_ the compount-statement, or the macro syntax would be difficult, requiring either
   fully-bracketing macros or double parens around the whole thing.

   Meanwhile, the wrapper object needs to be templatized to provide the correct typed operator()
   forwarding function.  My (JMD's) solution is to use an operator, which can take a second argument as
   trailing text without being wrapped in parens.  That is, M would expand to
       dummy| ^
   so that after the trailing text (not seen by the macro) you get:
       dummy| ^(ARGLIST){BLOCK}
   that is, the completed Apple Block Literal Expression becomes the second argument of the operator|,
   and my special object is the first argument.

   The operator| can be a template, and break open the Block type in the same manner as can be done
   for normal function pointer declarations.
For wrapping a C++ lambda, reason is different (add the decltype) but you still return an instance of a class with the right stuff in it.  The return value is a templated type, wrapper0<Ret>, wrapper1<Ret,A1>, or wrapper2<Ret,A1,A2> (etc) (an emulation of "..." for some fixed number of arguments)

So, the _type_ is not unique, but reused for each time the same operator() is needed.  The instance holds the underlying (wrapped) instance as a member.  For Apple Blocks, that is just their variation on a function pointer, so the type goes with the signature.
To wrap C++11 lamdas, the underlying instance has a unique type.  So use _that_ as the template argument, and generate another unique type that you can inherit from.

Using an operator| to add the wrapper, you can explicitly pull it in when needed along with any other filters that are being applied.