升级Boost至1.6.2+后boost::spirit解析器编译失败求助
Your hunch is spot-on—this problem directly stems from the Boost Variant behavior changes introduced in 1.6.2. Let's break down what's happening and how to fix it:
What's Going Wrong?
In Boost 1.6.1 and earlier, when a Variant couldn't directly hold a type, it would silently try implicit conversions to types it could hold. In your code, this meant an Acc object could be implicitly wrapped into a computationExpr, which in turn could be implicitly converted to an expr (since expr includes a recursive wrapper for computationExpr).
But the fixes for #5871 and #11602 in Boost 1.6.2 removed this behavior—Variant's constructor and assignment operator no longer participate in overload resolution if the input type can't be directly held. This breaks your _val = construct<Acc>(_1) line, because _val is of type expr, and there's no longer an implicit path from Acc to expr.
The Fixes
We need to explicitly bridge the type gap by wrapping Acc into a type that expr can directly accept. Here are a few clean ways to do this:
Option 1: Explicitly Construct computationExpr
Modify your rule action to wrap the Acc instance into a computationExpr before assigning to _val:
props_ = ( (lit("Acc") >> "(" >> int_ >> ")") [_val = computationExpr(boost::make_recursive_wrapper(construct<Acc>(_1)))] );
This directly creates a computationExpr (which expr supports) containing your Acc object, eliminating the need for implicit conversions.
Option 2: Directly Construct the Target expr
You can also build the expr instance directly, making the type conversion explicit:
props_ = ( (lit("Acc") >> "(" >> int_ >> ")") [_val = expr(computationExpr(boost::make_recursive_wrapper(Acc(_1))))] );
Option 3: Use a Helper Function for Clarity
If you want to keep your rule definition cleaner, create a small helper function to handle the conversion, then call it via Phoenix:
// Add this helper somewhere accessible (e.g., in Parser.cpp or a utility header) expr wrap_acc(const Acc& acc) { return computationExpr(boost::make_recursive_wrapper(acc)); } // Then update your rule: props_ = ( (lit("Acc") >> "(" >> int_ >> ")") [_val = boost::phoenix::bind(&wrap_acc, construct<Acc>(_1))] );
Why This Works
By explicitly constructing the intermediate computationExpr (with the recursive wrapper for Acc), we're giving expr a type it can directly hold—no more relying on implicit conversions that Boost Variant no longer allows. This aligns with the stricter type safety introduced in 1.6.2.
Bonus: Backward Compatibility
All these fixes will work in Boost 1.6.1 as well, so you won't break existing builds while fixing the newer version compatibility.
内容的提问来源于stack exchange,提问作者Aleph0

