[xpressive] semantic actions: is ref() necessary

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? 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)]); best regards -Thorsten

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

Eric Niebler skrev:
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?
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.
Right.
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.
Ok, but let me make the question more specific: why would you ever pass a container by value to push_back()?
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, _) ]);
Ok, that is neat, but I still don't get what you mean when you say or "know" the semantics of push_back, etc.. Don't we know the semantics? I thought the whole point was to call the member function called push_back on a container that supports that operation. -Thorsten

Thorsten Ottosen wrote:
Ok, but let me make the question more specific: why would you ever pass a container by value to push_back()?
Of course you wouldn't, but the first argument to push_back() may not, in fact, be a container. It may be an expression template that evaluates to a container. I could consider making push_back() "smart" and check whether its first argument is an expression template, or a terminal, or what, and assume any type it doesn't know about is a container that should be stored by reference, but this makes me uncomfortable. Now push_back() is special, and special cases makes things harder to learn. -- Eric Niebler Boost Consulting www.boost-consulting.com

Hello, A minor documentation error in the page http://igaztanaga.drivehq.com/intrusive/intrusive/using_smart_pointers.html <code> using namespace boost::intrusive; namespace ip = boost::interprocess; <snip>//Definition of the shared memory friendly intrusive listtypedef ip::list<shared_memory_data> shm_list_t;<code>typedef ip::list<shared_memory_data> shm_list_t; shouldn't betypedef list<shared_memory_data> shm_list_t;i.e. remove ip:: from ip::list?Best regards__________________________Vicente Juan Botet Escriba
participants (3)
-
Eric Niebler
-
Thorsten Ottosen
-
vicente.botet