Boost logo

Boost :

Subject: Re: [boost] Boost.Local Review (Nov 10, 2011 to Nov 19, 2011)
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-11-17 11:51:46


On Mon, Nov 14, 2011 at 8:32 PM, Lorenzo Caminiti <lorcaminiti_at_[hidden]> wrote:
> On Mon, Nov 14, 2011 at 7:53 PM, Vicente J. Botet Escriba
>>>> Is there any possible optimization/portability improvement to add the
>>>> return
>>>> type to the macro for the local function?
>>>
>>> The _only_ benefit in passing the result type within the macros is
>>> that when you also specify the types of all bound variables the
>>> library will not use Boost.Typeof. In other words, right now even if
>>> you specify the types of all bound variables `[const] bind(type)[&]
>>> var`, the library still has to use typeof to deduce the result type
>>> because such a type is not directly passed to the macros. I consider
>>> this a _very_ minor advantage largely outweighed by the better syntax
>>> achieved by moving the result type outside the macro.
>>>
>>> This is somewhat stated in the docs by the 3rd sentence of this
>>> subsection:
>>>
>>> https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_local/Advanced_Topics.html#boost_local.Advanced_Topics.specifying_bound_types
>>
>> Yes, I saw that. Don't you think that don't needing Boost.Typeof is a big
>> advantage? There are some compilers that don't supports yet, Typeof. For
>> them a specific macros would be welcome.
>
> Yes, I can add this feature by providing another macro like:
>
> /* no result type here */ FUNCTION_WITH_RESULT[_TPL]( result_type [,
> params_and_bindings] ) {
>    ...
> } FUNCTION_END( [inline | recursive] name )
>
> BLOCKS and EXITS always have void result so no need for an extra macro
> for them (if you specify the type for your bindings for BLOCKS and
> EXITS then they always use no typeof).
>
> That said, I need to closely look at the implementation to guarantee
> that no typeof is used when the result and binding types are specified
> in the macros.

Unfortunately, I have looked at the implementation and Boost.Typeof is
used by the FUNCTION_NAME macro to deduce the functor type :( It's a
long story (it has to do with support for recursive local
functions...) but I remember trying to not use typeof in NAME and I
couldn't get around it. Anyway, I will try again to get rid of typeof
in NAME. If I can do that (maybe even just for non recursive local
functions), I will support this syntax where the return type is
specified within the local function parameters (so I don't have to use
another macro ..._WITH_RESULT).

Expansion does not use typeof (maybe):

int y = 10;
BOOST_LOCAL_FUNCTION(int x, const bind(int) y, return int) { // (1)
    return x + y;
} BOOST_LOCAL_FUNCTION_END(int)
int z = int(1); // 11

Or, expansion uses typeof:

int y = 10;
int BOOST_LOCAL_FUNCTION(int x, const bind y) { // (2)
    return x + y;
} BOOST_LOCAL_FUNCTION_END(int)
int z = int(1); // 11

The same macro can deal with both syntaxes. If you specify the result
type in both places, outside and inside the macro `int
BOOST_LOCAL_FUNCTION(return int, ...) ...` then you'll get a
compile-time error.

IMPLEMENTATION NOTE: Parsing (1) and (2) might seem like arcane macro
magic but it's rather simple. It uses Boost.Local KEYWORD detection
and manipulation macros which are also at the basis the pp macros that
parse the more complex Boost.Contract syntax:
https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_local/Implementation.html#boost_local.Implementation.parsing_macros

Here's some sample code for the most curios:

// if elem starts with return `return xyz abc ...` expands to
// `xyz abc ...` (removing the leading return) otherwise
// expands to nothing (eating the 1-tuple)
#define FIND_RETURN(r, unused, elem) \
    IF(KEYWORD_IS_RETURN_FRONT(elem), \
        KEYWORD_RETURN_REMOVE_FRONT \
    , \
        TUPLE_EAT(1) \
    )(elem)

// apply macro above for each sequence element
#define FIND_RESULT_TYPE(seq) \
    SEQ_FOR_EACH(FIND_RETURN, ~, seq)

// transform `int x, const bind(int) y, return unsigned int`
// to pp-sequence (int x)(const bind(int) y)(return unsigned int)
// and apply macro above on generated pp-sequence
#define FIND_RESULT_TYPE(...) \
    FIND_RESULT_TYPE_SEQ(VARIADIC_TO_SEQ(__VA_ARGS__)

FIND_RESULT_TYPE(int x, const bind(int) y, return unsigned int) //
expand to `unsigned int` :)

Thanks.
--Lorenzo


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