I need to print a std::complex but omitting imaginary part if it's equal zero. So I have a rule with two productions:
karma::rule<OutputIterator, std::complex<double>()> complexRule =
'(' << double_ << ", " double_ << ')'
| double_ << omit[double_];
This way Karma will always choose the first production, so I need some kind of predicate which will make a decission. Boost Karma tutorial comes with that solution which requires adapting std::complex as a three element tuple.
BOOST_FUSION_ADAPT_ADT(
std::complex<double>,
(bool, bool, obj.imag() != 0, /**/)
(double, double, obj.real(), /**/)
(double, double, obj.imag(), /**/)
)
but unfortunately I cannot do that since other code is using std::complex adapted as two element tuple. Is there a way to solve that problem without adding predicate straight into Fusion adapter?
I was trying to use karma::eps generator as a predicate
auto rule = eps( ... ) << '(' << double_ << ", " << double_ << ')'
| double_ << omit[double_];
but I don't know what Phoenix expression should I put inside eps( ... ), and as Epsilon Generator doesn't consume any attribute I'm not sure if it is possible to access std::complex from it?
I'd personally stay away from adapting this as a sequence (I'm not sure how you adapted it as a two-element fusion sequence in the first place).
However it's done, it won't be generic (so you'll have use separate adaptations for different type arguments (
float
,double
,long double
,boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>>
etc.).This seems like a job for Spirit's customization points:
Now you can just use any
std::complex<T>
with a rule/expression expecting fusion sequence:Note how
duplicate[]
to test for0.0
before emitting the outputomit
to consume the imaginary part without displaying anythingHere's a full demo, Live On Coliru
Output: