Boost logo

Boost :

Subject: Re: [boost] Review Request: Variadic Macro Data library
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-02-19 10:48:37


On Fri, Feb 18, 2011 at 9:58 PM, Edward Diener <eldiener_at_[hidden]> wrote:
> On 2/18/2011 7:27 PM, Lorenzo Caminiti wrote:
>>
>> On Thu, Feb 17, 2011 at 5:13 PM, Edward Diener<eldiener_at_[hidden]>
>>  wrote:
>>>
>>> I am requesting that my library, the Variadic Macro Data library, which
>>> is
>>> in the sandbox in the variadic_macro_data directory, be reviewed for
>>> inclusion into Boost.
>>>
>>> The variadic_macro_data library adds support and functionality for
>>> variadic
>>> macros to Boost as well as integrating variadic macros with the Boost PP
>>> library without changing the latter library in any way.
>>>
>>> I believe others have used my library, can attest to its quality and that
>>> it
>>> does what it is supposed to do. and have found it useful when using
>>> variadic
>>> macros with Boost PP. I myself have used its functionality in my own TTI
>>> library in the sandbox. Support for variadic macros is implemented in
>>> nearly
>>> all modern C++ compilers and the syntax is natural for an end-user. The
>>> library is finalized as far as functionality is concerned and I would
>>> like
>>> to see it in Boost and am willing to maintain it as a Boost library.
>>
>> Is it possible to use variadic macros to detect empty parameters?
>
> My understanding of variadic macro data is that at least one parameter must
> be specified.
>
>>
>> For example:
>>
>> #include<boost/variadic_macro_data/VariadicMacroData.hpp>  // Proposed
>> lib.
>>
>> VMD_DATA_SIZE(1, 2) // 2
>> VMD_DATA_SIZE(1)    // 1
>> VMD_DATA_SIZE()     // 1 not 0 :((
>>
>> But I would like to the last size to expand to 0 (or have a different
>> macro that would expand to 0 in that case).
>>
>> With a real C99 preprocessor (e.g., GCC) I can do the following
>> because empty macro parameters are supported:
>
> Are they for variadic macro data in C++ ?

I think variadics and empty macro parameters are different things. C99
preprocessor (e.g., GCC) supports both while MSVC only supports
variadics. That is why I was wondering if variadics can be used to
detect empty macro parameters so I can do so also on MSVC.

On Mon, Sep 6, 2010 at 3:29 PM, Paul Mensonides <pmenso57_at_[hidden]> wrote:
> ...
> However, IS_EMPTY is _not_ a macro for general-purpose emptiness detection.
>  Its implementation requires the concatenation of an identifier to the front
> of the argument which rules out all arguments for which that isn't valid.
>  For example, IS_EMPTY(+) is undefined behavior according to all revisions
> of both the C and C++ standards (including the forthcoming C++0x).  Thus, at
> minimum, the argument must be an identifier (or keyword--same thing at this
> point) or a numeric literal that doesn't contain a decimal point.
>
> It is
> valid (and has been since C90) to pass something that expands to nothing as
> an argument to a macro.  However, it is not valid to pass nothing.  E.g.

See http://lists.boost.org/Archives/boost/2010/09/170639.php

> I will look at that and see what I can come up with. If variadic macros
> support an empty parameter list, I should provide a correct size of 0. If it
> does not I should indicate an error. So either way I will look to make a
> correction. Thanks for pointing this out.

This works on both MSVC and GCC :) Does it work on other
preprocessors? Can anyone please check?

#include <boost/variadic_macro_data/VariadicMacroData.hpp> // Proposed
lib in Boost's sandbox.
#include <boost/preprocessor.hpp>
#include <boost/preprocessor/facilities/is_empty.hpp>

VMD_DATA_SIZE(1, 2) // 2
VMD_DATA_SIZE(1) // 1
VMD_DATA_SIZE() // 1 not 0 :((

#define PP_VA_EAT(...) /* must expand to nothing */

#define PP_VA_SIZE_1OR0_(maybe_empty) \
        BOOST_PP_IIF(BOOST_PP_IS_EMPTY(maybe_empty (/*exapnd empty */) ), 0, 1)

#define PP_VA_SIZE_(size, ...) \
    BOOST_PP_IIF(BOOST_PP_EQUAL(size, 1), \
        PP_VA_SIZE_1OR0_ \
    , \
        size PP_VA_EAT \
    )(__VA_ARGS__ BOOST_PP_EMPTY)

#define PP_VA_SIZE(...) PP_VA_SIZE_(VMD_DATA_SIZE(__VA_ARGS__), __VA_ARGS__)

PP_VA_SIZE(1, 2) // 2
PP_VA_SIZE(1) // 1
PP_VA_SIZE() // 0 :))

The strange thing about this code is that `PP_VA_SIZE()` as well as
`VMD_DATA_SIZE()` don't give an error in the first place. They should
error because they are passed with an empty macro parameter (which is
not legal). It would have been legal instead to pass a parameter
expanding to empty like in `PP_VA_SIZE(BOOST_PP_EMPTY())` or
`VMD_DATA_SIZE(BOOST_PP_EMPTY())`.

Why `PP_VA_SIZE()` and `VMD_DATA_SIZE()` accept empty macro parameter?
Is that a variadic macros' feature or a MSVC bug?

>From http://www.open-std.org/JTC1/SC22/WG14/www/docs/C99RationaleV5.10.pdf
There must be at least one argument to match the ellipsis. This
requirement avoids the problems
that occur when the trailing arguments are included in a list of
arguments to another macro or
function. For example, if dprintf had been defined as
10 #define dprintf(format, ...) \
 dfprintf(stderr, format, _ _VA_ARGS_ _)
and it were allowed for there to be only one argument, then there
would be a trailing comma in
the expanded form. While some implementations have used various
notations or conventions to
work around this problem, the Committee felt it better to avoid the
problem altogether.
15 Similarly, the _ _VA_ARGS_ _ notation was preferred to other
proposals for this syntax.
A new feature of C99: Function-like macro invocations may also now
have empty arguments,
that is, an argument may consist of no preprocessing tokens. In C89,
any argument that
consisted of no preprocessing tokens had undefined behavior, but was
noted as a common
extension.
20 A function-like macro invocation f() has the form of either a call
with no arguments or a call
with one empty argument. Which form it actually takes is determined
by the definition of f,
which indicates the expected number of arguments.

>> BTW, a few minor comments on you library:
>> 1) I think a name like BOOST_PP_VA_... is better than BOOST_VMD. "VA"
>> is the same abbreviation for variadics that C99 uses in __VA_ARGS__
>> and Boost.Preprocessor already uses abbreviations like in
>> BOOST_PP_SEQ.
>
> What does the BOOST_PP_SEQ abbreviation have to do with BOOST_VMD_ ?

I was pointing out hat Boost.Preprocessor already uses some
abbreviation so "VARIADICS" doesn't necessarily need to be spelled out
completely.

>> Alternatively, I would consider BOOST_PP_VARIADICS_...
>> but still not "VMD" because programmers will not know what VMD stands
>> for.
>
> I used VMD to represent (V)ariadic(M)acro(D)ata, which is really what my
> library is about and also integrating that data with Boost PP. I rejected VA
> because its connotation in C++ is "variable argument(s)" and my library is

I think __VA_ARGS__ stands for VAriadics ARGumentS so VA only
abbreviates VAriadics. However, I couldn't find an actual standard
reference that explicitly defines what the word __VA_ARGS__ stands
for.

> about manipulating variadic macro data. I feel that something like VARIADICS
> is too long but I would certainly agree to it if others found it more
> expressive. I also do not want it to be BOOST_PP_ anything unless others
> decide it should be part of Boost PP and not its own library, and in that
> case I feel Paul Mensonides would need to find that acceptable.

IMO, library users would expect your library to be part of
Boost.Preprocessor. It's like adding another data set to
Boost.Preprocessor for variadics.

>> 2) I would add PP_VA_EAT, PP_VA_IDENTITY, PP_VA_CAT (similar to what
>> they do already in Boost.Preprocessor and they should be trivial to
>> implement). Also, I would add `#define PP_VA_SAME(...) __VA_ARGS__`.
>
> I am willing to add functionality to the library but I wonder where that
> would stop. Essentially variadic macro data is similar to any of the other

I agree, no point in duplicating Boost.Preprocessor API. However, in
using your library even just a bit I needed things like PP_VA_EAT,
PP_VA_IDENTITY, PP_VA_CAT to program control statements like
BOOST_PP_IIF, etc. While all of these are trivial to implement, it
would be annoying to to re-implement all these facility macros all the
times... It would be interesting to know what other programmer
experience is in using your library to decide which Boost.Preprocessor
control and facility macros are the most commonly used with variadics
arguments.

> data types in Boost PP in that it is really just a separate data type. Since
> the Boost PP data types already have a rich set of functionality I sort of
> feel that duplicating any of that functionality for variadic data itself
> will be redundant. This is especially true as my library has support for
> converting back and forth variadic data to any of the Boost PP data types. I
> feel pretty strongly that the use of variadic data with Boost PP should
> really be to provide a more pleasant syntax for the end-user, but once the
> programmer handles the variadic data he should convert it to a Boost PP data
> simply because that data type already has a rich set of functionality for
> dealing with the data.
>
> I would be willing to add BOOST_VMD_CAT and BOOST_VMD_IDENTITY since they
> are both trivial ( just call to the appropiate BOOST_PP_ macros passing
> __VA_ARGS__ ). Your last is just __VA_ARGS__ as you show. But I really

I often do:

#define DO_(p) // do something wiht p...
#define DO(cond, p) BOOST_PP_IIF(cond, DO_, p BOOST_PP_TUPLE_EAT(1))(p)

But I can't do this with variadic p because the IF will have too many
arguments is p is __VA_ARGS__. So SAME() would be handy:

#define PP_VA_SAME(...) __VA_ARGS__
#define DO_(...) // do something with __VA_ARGS__...
#define DO(cond, ...) BOOST_PP_IIF(cond, DO_, PP_VA_SAME)(__VA_ARGS__)

> wonder if more functionality on variadic macro data is really worth it
> considering that the goal of the library, other than letting the end-user
> access individual tokens in the variadic macro data itself, is to convert
> back and forth to the Boost PP data types. I can understand that an end-user
> of the library such as yourself might want a number of additional operations
> on the variadic macro data itself, but I think if you look at the Boost PP
> data types you will see that their rich functionality offers most anything
> one would want to do with the data once you get it.

-- 
Lorenzo

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