Boost logo

Boost :

Subject: Re: [boost] Rave for proposed Boost.Local (functions)
From: Jeffrey Lee Hellrung, Jr. (jhellrung_at_[hidden])
Date: 2011-02-07 03:42:45

On 2/6/2011 8:45 PM, Steven Watanabe wrote:
> On 2/6/2011 8:09 PM, Jeffrey Lee Hellrung, Jr. wrote:
>> On 2/6/2011 5:46 PM, Lorenzo Caminiti wrote:
>>> On Sun, Feb 6, 2011 at 3:23 PM, Jeffrey Lee Hellrung, Jr.
>>> <jhellrung_at_[hidden]> wrote:
>>>> On 2/6/2011 9:17 AM, Lorenzo Caminiti wrote:
>>>> [...]
>>>>> boost::scope_exit::aux::declared< boost::scope_exit::aux::resolve<
>>>>> sizeof(boost_local_auxXargs)>::cmp1<0>::cmp2>
>>>>> boost_local_auxXargs;
>>>> Shouldn't the name boost_local_auxXargs have some kind of line
>>>> number or
>>>> counter or function name pasted into it to prevent name collision of
>>>> multiple BOOST_LOCAL_FUNCTION declarations in the same scope?
>>> No, this has to be a global extern variable declared as:
>>> extern boost::scope_exit::aux::undeclared boost_local_auxXargs;
>>> in one of Boost.Local headers. It's a trick carried over 100% from
>>> Boost.ScopeExit (as I understand it, this is because only global or
>>> static variables can be used from within a nested block
>> Ugh, okay ;) Will read the link.
> That link isn't very relevant. This code is one
> of the most awful hacks around. Basically, it
> takes advantage of the template argument list/
> comparison operator ambiguity to declare a variable
> iff it hasn't already been declared in that scope.
> The second occurrence is parsed as
> (boost::scope_exit::aux::declared< (boost::scope_exit::aux::resolve<
> sizeof(boost_local_auxXargs)>::cmp1
> < 0)>::cmp2 >
> boost_local_auxXargs);
> which is a no-op.
> In Christ,
> Steven Watanabe Thanks Steven.

At the risk of being off-topic, I strongly feel compelled to ask some
follow-up questions...

As I understand it, the first occurrence within a given scope is parsed as

         sizeof( boost_local_auxXargs )
>::cmp1< 0 >::cmp2
> boost_local_auxXargs;

which is a declaration of a variable called boost_local_auxXargs in
local scope which *hides* the variable of the same name from the global
scope. Thus all subsequent references to boost_local_auxXargs in this
scope refer to this variable. But I don't really understand how the
extern global declaration ties into this, gives sizeof(
boost_local_auxXargs ) meaning...? Why is the extern keyword necessary
in the global declaration? Wouldn't something like

const boost::scope_exit::aux::undeclared boost_local_auxXargs = { };

(at global scope) suffice?

As Steven explained, the second occurence within a scope is parsed as
(rearranging the formatting a little)

         sizeof( boost_local_auxXargs )
>::cmp1 < 0)
>::cmp2) > boost_local_auxXargs;

which amounts some greater-than comparison between
boost::scope_exit::aux::declared< ... >::cmp2 and boost_local_auxXargs
(presumably overloaded to be a no-op). So what precisely is it about
the second occurrence that causes it to be parsed differently? Is the
rule (roughly) that if there is an ambiguity, try parsing as if it's a
variable declaration, and if that fails (for any of a number of reasons,
one of which is the variable has already been declared in *this* scope),
then try an alternative parse? What is the logic one goes through to
parse this expression?

Looking back at the macro expansion Lorenzo supplied, it seems the only
use for this boost_local_auxXargs variable is to hold a definite
reference to the bound variables struct to be used within
BOOST_LOCAL_FUNCTION_END( xxx ). I can see the necessity of this for
local function passed to it, which should be unique to the scope, hence
could be used to construct a unique name for the reference to the bound
variables struct. So it seems this "awful hack" wouldn't be necessary
for (proposed) Boost.Local. Am I missing something?

Again, apologies if this is too off-topic, but Steven's explanation
really put a "WTF" look on my face (directed toward this "awful hack",
not Steven).

- Jeff

Boost list run by bdawes at, gregod at, cpdaniel at, john at