Boost logo

Boost :

Subject: [boost] [lambda] [result_of] Lambda enhancements
From: Adam Butcher (dev.lists_at_[hidden])
Date: 2010-04-01 13:46:08


Hi

Perhaps this would have been better as two separate mails but since it
is all lambda related I have included it as one (despite one patch
actually being to the result_of library).

[lambda]

I discovered recently that member-function-ptrs wrapped in boost::lambda
objects do not apply directly if the subject is held in a smart-ptr
(unless that smart-ptr has an implicit conversion to T*). There are a
number of places in our code base where we have worked around this by
using something like *free1 rather than simply free1 which ends up
calling the 'apply member-function to object-by-reference' adaptor.
This works providing the smart-ptr defines a type 'element_type' to be
the underlying object type (as shared_ptr et al do). It does not work
for third-party smart-ptrs that do not define this type.

It struck me that since boost.bind uses boost.mem_fn's get_pointer
template to handle this use case it would be reasonable to add an
overload of 'apply' to lambda/detail/function_adaptors.hpp that deferred
to that. I knocked up a perl script which adds the necessary overloads
to each specialization in function_adaptors which I have attached (I
have also attached the resulting diff). It may be that this yields some
unpleasant side-effects that I haven't thought of or observed but so far
it seems to work okay with our code base. The get_pointer overload is
disabled if the argument is convertible to ref-to-const-object-type
(e.g. if it is a derived type) since then the reference overload should
be used. I would appreciate any feedback on the idea and
implementation.

[result_of]

Whilst implementing a front-end template for a set of functions that
accept boost.function objects with various return types, I discovered
that boost.result_of does not implement support for the nested
sig<tuple> template used by boost.lambda objects. My intent was to
accept any user-supplied function at the front-end and, based on the
given function's return type when applied to a specific set of
arguments, forward to the appropriate implementation. This
determination currently fails if the user supplies a lambda object.

The attached result_of patch adds detection of the nested sig template
in order to support determining the return type of lambda functions
(providing the necessary arguments are given). This is done in a
non-intrusive way; i.e. there is no physical dependency on boost.lambda
or boost.tuple, though the boost.tuple classes 'cons' and 'null_type'
are forward declared. Since they are only ever instantiated when a
boost.lambda object is provided (which will have already brought in
their definitions) I think it should be okay. In order to provide the
sig template with its required tuple, a facility has been added (with
implementation generated by some additional preprocessor code) that
converts from function-type to tuple (i.e. F(A,B...) -> cons<F,cons<A,
cons<B,...null_type>>>). Since only the type declarations are required
this can be done without pulling in any tuple headers.

One thing I am a little concerned about is that the determination
mechanism for the existence of the sig template is probably not very
portable (I have only tried it on GCC 4 and VC9).

Is there an MPL/type_traits predicate generator for portable nested
template detection? I am aware of BOOST_MPL_HAS_XXX_TRAIT_(NAMED_)DEF
but I couldn't see any generator around that area that would do nested
template detection. We have such a facility in our code base but it
will have only been tried on GCC 4 and VC9 (maybe also VC7.1).

Again I would appreciate any feedback on these diffs and whether or not
they are suitable for inclusion into the respective libraries.

Regards,
Adam






Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk