
On 2/6/2011 8:45 PM, Steven Watanabe wrote:
AMDG
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@ucla.edu> 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 http://lists.boost.org/Archives/boost/2006/11/113658.php).
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
Ummm...wow. 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 boost::scope_exit::aux::declared< boost::scope_exit::aux::resolve< 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, except...it 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) (boost::scope_exit::aux::declared< (boost::scope_exit::aux::resolve< 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 BOOST_SCOPE_EXIT_END, but BOOST_LOCAL_FUNCTION_END has the name of the 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