
Thorsten Ottosen wrote:
Hi Eric,
My semantic actions might look like
+(name[push_back(ref(causeNames),as<std::string>(_) )]);
My first question here is whether ref() is really necessary?
In your example from the documentation, I can better understand it:
[ ref(result)[s1] = as<int>(s2) ];
because you apply the [] operator to the result.
But otherwise, is there any time you not want a reference stored? In my case above, couldn't the destructor of push_back() take a T& argumentment and construct a lazy reference from that?
The issue is one of lifetime management. Consider: sregex make_regex( int &i, int j ) { sregex rx = (some >> regex)[ ref(i) += j ]; // TODO return rx; } What happens to 'j'? If we follow your suggestion, 'j' should be held by reference. Then when make_regex returns, the resulting regex object is left holding a dangling reference to an int. That's why anything not wrapped in ref() is held *by value* by the regex. So that's why ref() is needed in your case. Have a look at xpressive::local<> and xpressive::reference<> as ways of decorating an object so that xpressive knows how to store it in an action.
I also have another question: is it really necessary to write the as<std::string>(_) part of the semantic action?
Can this type not be deduced from the template argument to push_back()? In my case it would simply be Container::value_type.
If so, we would end up with the really slick looking
+(name[push_back(causeNames)]);
No, push_back takes two arguments, and I don't want to get into the game of making xpressive semantic actions too clever by a half by trying to guess what you mean, or "know" the semantics of push_back, etc.. However, in a semantic action, _ stands in for a sub_match object, which happens to have an implicit conversion to std::string. So this should work: // Untested. local<std::vector<std::string> > causeNames; sregex rx = +(name[ push_back(causeNames, _) ]); HTH, -- Eric Niebler Boost Consulting www.boost-consulting.com