I have yet another blocker issue with Spirit Qi.
I have implemented error handling in a functor struct called error_handler. This is passed to the grammar constructor by reference (see the MiniC example for Qi).
I then have on_error<fail>
s defined in the grammar's constructor:
typedef boost::phoenix::function<error_handler<> > error_handler_function;
on_error<fail>(gr_instruction,
error_handler_function(err_handler)(L"Error: Expecting ", _4, _3));
// more on_error<fail>s...
However, my error_handler
has private members. It seems every time on_error
is invoked, the err_handler
object is copied, hence once the functor leaves, the local variables changed are destroyed.
I tried passing the handler by reference:
typedef boost::phoenix::function<error_handler<>& > error_handler_function; // <--- Note the ampersand!
on_error<fail>(gr_instruction,
error_handler_function(err_handler)(L"Error: Expecting ", _4, _3));
// more on_error<fail>s...
However, the problem remains: on_error()
works on copies of err_handler
, not a single instance!!
I have also tried variations of boost::phoenix::ref(err_handler)
with nothing but compile errors.
Surely, there must be an easy solution to passing the handler via reference?
I would appreciate any input. Thank you for your help.
Yes, phx::bind and phx::function<> will take their wrapper calleables by value by default. However.
Let's say[1], you have an error handler like this... minimalist example:
(As you can see I made it explicitely non-copyable to ensure the compiler wouldn't silently generate the code behind my back.)
Now, I'm not sure whether this is a combination you accidentally missed, but:
works nicely, as does
Note that because
bind
takes a reference, we need to ensure lifetime oferr_handler
matches (or exceeds) that of the parser, so I madeerr_handler
a member of the parser class.When I pass it input to fail, my program will be able to print
proof
of the invocations ofmy_error_handler
:As always, a completely integrated sample program:
When fed the input
It prints (as the first/last lines)
[1] It's not the first time I'm having to imagine relevant code