Boost logo

Boost :

From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2005-12-30 00:14:17


> -----Original Message-----
> From: boost-bounces_at_[hidden]
> [mailto:boost-bounces_at_[hidden]] On Behalf Of Arkadiy Vertleyb

> > Which looping constructs does it use?
>
> Currently at least the following:
>
> REPEAT
> ENUM
> SEQ_ENUM
> SEQ_FOR_EACH_I
> SEQ_FOLD_LEFT

Which one is failing?

> > "recursion state" (such as 'z' for REPEAT), then it is best
> to provide
> both:
> >
> > #define REGISTER(...) REGISTER_Z(DEDUCE_Z(), ...) #define
> > REGISTER_Z(z, ...) // ...
>
> Is there any significant benefit of specifying z manually?
> Does it depend on the depth of nesting (typeof just has a
> sequence inside another sequence)?

There *can* be a significant benefit in speed, but it usually isn't from a top
level invocation. I.e. at the top-level, REPEAT should always be used directly
(and let it deduce 'z' itself). But, inner REPEAT's can be a lot more efficient
if it doesn't have to deduce 'z' repeatedly. For example,

#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>

#define FIXED(z, n, x) \
    BOOST_PP_COMMA_IF(n) x \
    /**/
#define TTP(z, n, id) \
    BOOST_PP_COMMA_IF(n) \
    template< \
        BOOST_PP_REPEAT(BOOST_PP_INC(n), FIXED, class) \
> class BOOST_PP_CAT(id, n) \
    /**/

BOOST_PP_REPEAT(50, TTP, T)

The inner REPEAT in TTP deduces 'z' over and over and over, which is a waste of
time. 'z' is already known (passed as an argument), so it is more efficient to
use it:

#define TTP(z, n, id) \
    BOOST_PP_COMMA_IF(n) \
    template< \
        BOOST_PP_REPEAT_ ## z(BOOST_PP_INC(n), FIXED, class) \
> class BOOST_PP_CAT(id, n) \
    /**/

Likewise, it is convenient for other macros that need 'z' (explicitly or
implicitly) to provide variants that take it as an argument. Those variants
aren't the primary interface, but they leave the efficiency choice to the user.

In the case of 'z', the deduction is doing a binary search on only three
possible values for 'z', so it isn't all that significant. For 'd', on the
other hand, it is doing a somewhat more significant binary search on 256
possible values.

However, I think that if your macro is using multiple different library
recursion states (e.g. 'z' and 'd'), you might as well just have a single
automatic interface. Most-likely-to-be-minor efficiency gains aren't worth a
combinatorial explosion of interfaces.

[This whole thing is the pp-lib's greatest problem. There is no unifying and
extensible way that recursion is accomplished. Instead, there are multiple
recursion states that aren't very extensible without macro replication. Chaos
solves this problem completely, but the techniques used are way too advanced for
what can be put into Boost.]

Regards,
Paul Mensonides


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