Boost Karma - 非消耗谓词 [英] Boost Karma - non consuming predicate
问题描述
我需要打印std ::复杂,但如果它等于零,则省略虚部。所以我有一个有两个产生式的规则:
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_];
这样Karma将总是选择第一个产品,所以我需要某种谓词,解除。 Boost Karma教程
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(), /**/)
)
$ b b
但不幸的是我不能这样做,因为其他代码使用std ::复杂适应作为两元素元组。有没有办法解决这个问题,而不添加谓词直接进入Fusion适配器?
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?
我试图使用 karma :: eps generator 作为谓词
auto rule = eps( ... ) << '(' << double_ << ", " << double_ << ')'
| double_ << omit[double_];
但我不知道什么Phoenix表达式应该放在eps作为Epsilon生成器不消耗任何属性我不确定是否可以从它访问std ::复杂?
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).
但是它已经完成了,它不会是通用的(所以你将使用单独的适应不同的类型参数( float
, double
,
long double
, boost :: multiprecision :: number< boost :: multiprecision :: cpp_dec_float< 50> code>等)。
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.).
这似乎是Spirit的 自定义点 :
This seems like a job for Spirit's customization points:
namespace boost { namespace spirit { namespace traits {
template <typename T>
struct extract_from_attribute<typename std::complex<T>, boost::fusion::vector2<T, T>, void>
{
typedef boost::fusion::vector2<T,T> type;
template <typename Context>
static type call(std::complex<T> const& attr, Context& context)
{
return { attr.real(), attr.imag() };
}
};
} } }
现在你可以使用 std :: complex< T>
使用规则/表达式预期融合序列:
Now you can just use any std::complex<T>
with a rule/expression expecting fusion sequence:
rule =
'(' << karma::double_ << ", " << karma::duplicate [ !karma::double_(0.0) << karma::double_ ] << ')'
| karma::double_ << karma::omit [ karma::double_ ];
请注意
- 在发出输出之前,我使用
duplicate []
来测试0.0
/ li>
- 在另一个分支上,我使用
omit
来消耗虚部而不显示任何内容
- I used
duplicate[]
to test for0.0
before emitting the output - On the other branch I used
omit
to consume the imaginary part without displaying anything
这是一个完整的演示, Live On Coliru
Here's a full demo, Live On Coliru
#include <boost/spirit/include/karma.hpp>
#include <complex>
namespace boost { namespace spirit { namespace traits {
template <typename T>
struct extract_from_attribute<typename std::complex<T>, boost::fusion::vector2<T, T>, void>
{
typedef boost::fusion::vector2<T,T> type;
template <typename Context>
static type call(std::complex<T> const& attr, Context& context)
{
return { attr.real(), attr.imag() };
}
};
} } }
namespace karma = boost::spirit::karma;
int main()
{
karma::rule<boost::spirit::ostream_iterator, boost::fusion::vector2<double, double>()>
static const rule =
'(' << karma::double_ << ", " << karma::duplicate [ !karma::double_(0.0) << karma::double_ ] << ')'
| karma::double_ << karma::omit [ karma::double_ ];
std::vector<std::complex<double>> const values {
{ 123, 4 },
{ 123, 0 },
{ 123, std::numeric_limits<double>::infinity() },
{ std::numeric_limits<double>::quiet_NaN(), 0 },
{ 123, -1 },
};
std::cout << karma::format_delimited(*rule, '\n', values);
}
输出:
(123.0, 4.0)
123.0
(123.0, inf)
nan
(123.0, -1.0)
这篇关于Boost Karma - 非消耗谓词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!