Boost logo

Boost :

Subject: Re: [boost] Alternative implementation for BOOST_PP_VARIADIC_SIZE
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-11-15 04:44:59


On Mon, Nov 14, 2011 at 11:35 PM, Paul Mensonides <pmenso57_at_[hidden]> wrote:
> On Mon, 14 Nov 2011 19:57:31 +0000, Jens Gustedt wrote:
>
>> I think any macros that are designated to be used by an "end user" must
>> mediate between those different views and provide an end result that
>> reads well for that end user, who I think expects syntax written as if
>> it where core language.
>>
>> In P99 I use the IS_EMPTY macro for exactly that, try to accommodate
>> that supposed expectation.
>
> I strongly disagree that catering to that expectation is a good thing in
> any context.  The sooner people realize (and expect) that the preprocessor
> behaves differently than the core language, the better.  Virtually all
> issues related to the misuse of the preprocessor stems from attempting to
> make object-like macros look like constant variables and function-like
> macro invocations look like underlying-language function calls.  At best,
> the correlation between function-like macro invocations and function calls
> should be incidental.  It should never be considered to be a goal.  That
> is a fundamentally broken mentality.
>
> Preprocessing directives and macro invocations are part of an EL (DSEL
> without the DS) that overlays the underlying language; they are not part
> of the syntax or semantics of the underlying language.  The preprocessing
> phases of translation are best thought of as a executing a program
> overlaid on the source that translates that source into a token sequence
> presented to the C or C++ parser.  Anything else is just perpetuating the
> problem.
>
> While it is not my business to force anyone to do anything, I am certainly
> not going to write code which may be viewed as best practice that
> intentionally perpetuates that mentality.  And this really is about that
> mentality.  It isn't about the slight syntactic inconvenience.  Sure, with
> a sequence (a)(b)(c), that's a lot of extra parentheses (and you get other
> benefits with sequences such as elements containing commas and data
> structures with unbounded length), but a tuple (a,b,c) does not have a lot
> of extra parentheses.  You'd get MACRO() vs. MACRO((a,b,c)) which has an
> incidental two extra parentheses and the two invocation cases are
> unambiguously, compiler-error-free detectable as different.  The only
> supposed "downside" is that it doesn't look like a regular function call
> which is a symptom of the above mentality and is not actually a downside
> (it might even be an upside given the status quo which has been around
> since the early days of C).
>
> With an interface macro without a certain domain (where the necessary
> domain restrictions are reasonable), it really depends on the reuseability
> level of the interface.  Otherwise, there are serious repercussions
> related to recursion inherent in any forwarding interface (i.e. convert-
> and-forward) unless you do something with recursion like Chaos does which
> requires an extremely good preprocessor.
>
> In the typical case, it is never a good idea, even at the interface
> level.  In some more advanced cases, it isn't that big a deal.  For
> example, in Lorenzo's (sp?) contract programming library, the syntax is so
> blatantly not that of the underlying language and the domain is specific
> enough that he can get away with it without it being particularly
> adverse.  In that case, the resulting syntax is blatantly a DSEL and
> therefore can have whatever syntax it wants since confusion between
> different "languages" is nearly impossible.  That scenario, however, is

For example:

    CONTRACT_FUNCTION_TPL(
    public void (push_back) ( (const T&) val )
        precondition( size() < max_size() )
        postcondition(
            auto old_size = CONTRACT_OLDOF size(),
            auto old_capacity = CONTRACT_OLDOF capacity(),
            back() == val, requires boost::has_equal_to<T>::value,
            size() == old_size + 1,
            capacity() >= old_capacity
        )
    ) {
        vect_.push_back(val);
    }

> quite a bit different than some macro just defined as A(a, b, ...) as
> opposed to A((a, b, ...)) or A((a)(b)(c)) just to make it look like a
> function call.

--Lorenzo


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