Boost logo

Boost Users :

Subject: Re: [Boost-users] [Range & c++0x Lambdas] Can this be done?
From: John M. Dlugosz (mpbecey7gu_at_[hidden])
Date: 2012-11-24 11:01:13


------------------------------ Message: 3 Date: Thu, 22 Nov 2012 11:31:05 -0800 From:
"Jeffrey Lee Hellrung, Jr." <jeffrey.hellrung_at_[hidden]> To: boost-users_at_[hidden]
Subject: Re: [Boost-users] [Range & c++0x Lambdas] Can this be done? Message-ID:
<CANvXPuQmePirYFadBKRyVoQur1N8DH2c-QhwqHgZMV2MNfG_gQ_at_[hidden]> 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.



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net