gpt4 book ai didi

c++ - Boost Karma - 非消耗谓词

转载 作者:搜寻专家 更新时间:2023-10-31 01:44:44 25 4
gpt4 key购买 nike

我需要打印一个 std::complex 但如果它等于零则省略虚部。所以我有两个作品的规则:

karma::rule<OutputIterator, std::complex<double>()> complexRule = 
'(' << double_ << ", " double_ << ')'
| double_ << omit[double_];

这样 Karma 将始终选择第一个产生式,因此我需要某种可以做出决定的谓词。 Boost Karma tutorial该解决方案附带需要将 std::complex 改编为三元素元组。

BOOST_FUSION_ADAPT_ADT(
std::complex<double>,
(bool, bool, obj.imag() != 0, /**/)
(double, double, obj.real(), /**/)
(double, double, obj.imag(), /**/)
)

但不幸的是我不能这样做,因为其他代码正在使用 std::complex 改编为两个元素元组。有没有一种方法可以在不直接将谓词添加到 Fusion 适配器中的情况下解决该问题?

我正在尝试使用 karma::eps generator作为谓词

auto rule = eps( ... ) << '(' << double_ << ", " << double_ << ')'
| double_ << omit[double_];

但我不知道应该在 eps( ... ) 中放入什么 Phoenix 表达式,并且由于 Epsilon 生成器不使用任何属性,我不确定是否可以从中访问 std::complex ?

最佳答案

我个人不会将其改编为序列(我不确定您最初是如何将其改编为双元素 fusion 序列)。

无论如何完成,它都不是通用的(因此您将对不同类型的参数( floatdoublelong doubleboost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>> 等)使用单独的改编。

这似乎是 Spirit 的 的工作 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() };
}
};

} } }

现在你可以使用any std::complex<T>具有期望 fusion 序列的规则/表达式:

 rule = 
'(' << karma::double_ << ", " << karma::duplicate [ !karma::double_(0.0) << karma::double_ ] << ')'
| karma::double_ << karma::omit [ karma::double_ ];

注意如何

  • 我用了duplicate[] 测试 0.0在发出输出之前
  • 在另一个分支上我使用了omit消耗虚部而不显示任何内容

这是一个完整的演示, 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)

关于c++ - Boost Karma - 非消耗谓词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23079143/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com