Boost logo

Boost :

From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2006-01-29 10:06:57


> -----Original Message-----
> From: boost-bounces_at_[hidden]
> [mailto:boost-bounces_at_[hidden]] On Behalf Of Tobias Schwinger

> >> [...] which creates pathological input that IF cannot deal with:
> >> [...]
> >
>
> While we're at it:
>
> This code (taken from boost/typeof/vector.hpp, line 106)
>
> BOOST_PP_IF(n, BOOST_PP_EMPTY(), class T = void)
>
> seems to contain a similar (but more subtle) problem.
>
> Emptiness (well, deferred emptiness in this case, to be
> precise) is passed to BOOST_PP_IF as the second argument, and
> empty input (to the macros used by BOOST_PP_IF internally)
> results in undefined behaviour -- so it's up to the
> preprocessor whether things work correctly or not.

This is exactly right. In current C++, empty arguments amount to undefined
behavior. Many preprocessors allow it, and C99 requires it to work, but it
*shouldn't* work in current C++.

> For a quick fix, a more bullet-proof version could look like this
>
> BOOST_PP_IF(n,BOOST_PP_EMPTY,BOOST_PP_IDENTITY(class T = void))()
>
> or
>
> BOOST_PP_EXPR_IIF(BOOST_PP_NOT(n), class T = void)

The latter of the two is the better solution, IMO. You could also do:

BOOST_PP_IF(
    n,
    BOOST_PP_TUPLE_EAT,
    BOOST_PP_TUPLE_REM
)(1)(class T = void)

This allows the 'class T = void' part to be a macro invocation that is lazily
evaluated (or at least, is _supposed_ to be lazily evaluated). E.g.

BOOST_PP_IF(
    n,
    BOOST_PP_TUPLE_EAT,
    BOOST_PP_TUPLE_REM
)(1)( EXPENSIVE_MACRO_INVOCATION() )

...where EXPENSIVE_MACRO_INVOCATION() is only invoked if 'n' is 0.

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