Boost logo

Boost :

Subject: [boost] [preprocessor] Variadics suggestion
From: Kitten, Nicholas (nkitten_at_[hidden])
Date: 2012-09-24 16:15:34


Hi Folks,

First of all, I'd like to say "thank you" to Edward Diener and Paul
Mensonides for incorporating variadics support into
Boost.Preprocessor, which has been on my wishlist for a long time.

In fact, I wanted it badly enough that I've been using my own slightly
modified version of the library assuming variadics for a while now,
and I was interested to see what a cross-platform version would look
like (mine was only tested on MSVC). I think the chosen approach of
converting variadics to non-variadics is probably superior to the
breaking algorithm changes I made in my own version, and I would
humbly suggest a few more additions in the same spirit.

The reason I chose to use variadics in the first place was to simplify
the user interface for the common case of manipulating what I'll call
a "variadic sequence," (a series of concatenated tuples), which I
wanted to look similar to the following:

#define FILTER_PARAMETERS (A, int, 3)\
                                                    (B, float, 2.0f)\
                                                    (C, const char*, "Howdy!")

Of course, without variadics you need either a set of macros for each
tuple size, or else double parenthesis around each tuple, which
becomes even more burdensome when users are also required to
parenthesize inner arguments, leading to gems like this one:

#define FILTER_PARAMETERS ((A, (TypeConverter<double, float>),
(TypeConverter<double,float>()))

My solution admitting the preferred format was to replace most private
SEQ_*(X) macros with SEQ_*(...), which also required modifying
SEQ_ELEM() and SEQ_HEAD() to return (X) instead of X. However, it
occurs to me now that a conversion function to go from variadic to
regular sequences would've been easier to implement and backwards
compatible; see the attached file, which I've tested in basic cases on
MSVC 10 and gcc-4.3.4. The usage would be:

#define SEQ (a,b,c)(1,2,3,4)
BOOST_PP_VARIADIC_SEQ_TO_SEQ( SEQ ) // expands to ((a,b,c))((1,2,3,4))

I'm submitting this because I couldn't find a way to use some
combination of TUPLE/VARIADICS and SEQ transformations to do the same
thing succinctly, but if I'm just missing something, please let me
know.

Next, I would suggest having a documented IS_EMPTY(...) function for
detecting an empty variadic list. Since is_empty.hpp already exists
for single arguments (though undocumented), I would guess the variadic
version would look quite similar. My own (MSVC) version is attached.

Finally, I would suggest using the preceding IS_EMPTY(...) function to
allow VARIADIC_SIZE(...) to return 0, i.e. something along the lines
of:

# define BOOST_PP_VARIADIC_SIZE(...) BOOST_PP_IIF(
BOOST_PP_IS_EMPTY(__VA_ARGS__), 0, BOOST_PP_VARIADIC_SIZE_I(
__VA_ARGS__ ) )

where BOOST_PP_VARIADIC_SIZE_I is the current definition of
BOOST_PP_VARIADIC_SIZE.

Thanks,
-Nick Kitten

Software Engineer
Center for Video Understanding Excellence

ObjectVideo, Inc.





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