
On Mon, Nov 14, 2011 at 6:14 AM, Gennadiy Rozental <rogeeff@gmail.com> wrote:
Paul Mensonides <pmenso57 <at> comcast.net> writes:
On Sun, 13 Nov 2011 21:10:11 -0800, Jeffrey Lee Hellrung, Jr. wrote:
I'm just curious, is
-------- #define A(...) A(,) --------
legal?
Yes. "Empty" is a valid argument in >= C99 and >= C++0x. An example of when an empty argument actually appears when passing around a cv- qualifier: nothing | const | volatile | const volatile. This is only one of many many scenarios where emptiness is a valid element and has meaning.
Yes. This all is "legal" and "valid", but does it have meaning? I doubt it.
Show me sane example where one would develop macro FOO which takes two arguments and tell users to invoke it like this FOO(,) or FOO(a,) or FOO(a,b). Instead one can present a macro which takes variadic data and does different things depending on how many arguments passed (0, 1, or 2). So the invocations would look like FOO(), FOO(a), FOO(a,b) - much better IMO.
IMO, the point is that there is nothing wrong with you providing FOO(a, b) to your end users so as part of your public API and document that it should never be called as FOO(,). Then you internally convert the variadic `a, b` to the sequence (a)(b) and do your pp manipulations internally using pp-sequences. This way the Boost.Preprocessor library that you use to implement your internals supports a sound and scalable pp data structure (sequence) and your users benefit from using the variadic syntax that is more natural to them-- everyone wins :). My Boost.Local and Boost.Contract libraries follow this exact same pattern.
FOO(,) is a stone in a road to awk-like hell and should be strictly forbidden from the end user code. It might only be used in some corner cases deep in library code and never exposed.
So, all the theoretical corner cases aside FOO() should be invocation with zero arguments and FOO(a) with one.
I disagree, this is not theoretical. If you write a general purpose library like Boost.Preprocessor you need to make sure it is general (not theoretical) in that it handles all the uses cases that can arise within what the C++ standard specifies (including corner use cases). Otherwise, as the Boost.Preprocessor author you will be making assumptions like "my users will _never_ have to use a macro FOO(,)" which might be true in most but no all cases. HTH, --Lorenzo