gpt4 book ai didi

c++ - 是否可以将一个 Action 附加到 boost::spirit::rule 解析器,该解析器将解析结果分配给(尚未)未知实例的成员?

转载 作者:太空狗 更新时间:2023-10-29 19:58:54 28 4
gpt4 key购买 nike

我试图从 boost::spirit 规则定义的 Action 中引用一个(尚未)未知实例的成员,所以在伪代码中,

代替 double_[ref(rN) = _1]我正在寻找类似的东西 X** ppx; double_[ref(&X::rN, ppx) = _1]

它的一个解决方法可能是一个简单的“语义 Action ”,带有一个知道实例并能够写入它的参数,比如

qi::rule<Iterator, Skipper> start;
my_grammar(DataContext*& dataContext) : my_grammar::base_type(start) , execContext(execContext) {
start = qi::double_[ boost::bind(&my_grammar::newValueForXY, dataContext, ::_1) ];

但是,我想知道是否有可能直接“绑定(bind)”到成员变量,就像可以使用“phoenix::ref(...) = value”绑定(bind)到“本地”变量一样。

我尝试了以下语法:

start = qi::int_[ boost::bind<int&>(&DataContext::newValueForXY, boost::ref(dataContext))() = ::_1] ];

但由于 VS2010SP1 和错误消息而失败

error C2440: '=': 'boost::arg' 无法转换为 ...

最佳答案

有几种方法可以给这只猫剥皮:

  1. 您可能想到了延迟执行 bind 表达式:phx::bind 可以做到这一点
  2. 或者,您可以为此使用属性传播(完全不用语义操作)
  3. 最后,您可以使用继承属性(例如,当 DataContext 没有默认构造函数或复制成本很高时)

1。延迟与 Phoenix 的绑定(bind)

为此目的使用 phoenix bind:这将产生一个 Phoenix actor,在触发语义 Action 时将“延迟执行”。

这是您可能一直在寻找的缺失代码示例的重建:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi = boost::spirit::qi;
namespace phx= boost::phoenix;

struct DataContext
{
double xy;
};

template <typename Iterator, typename Skipper>
struct my_grammar : qi::grammar<Iterator, Skipper>
{
my_grammar(DataContext& dataContext) : my_grammar::base_type(start)
{
start = qi::double_
[ phx::bind(&my_grammar::newValueForXY,
phx::ref(dataContext),
qi::_1) ];
}
private:
static void newValueForXY(DataContext& dc, double value)
{
dc.xy = value;
}

qi::rule<Iterator, Skipper> start;
};

int main()
{
const std::string s = "3.14";

DataContext ctx;

my_grammar<decltype(begin(s)), qi::space_type> p(ctx);
auto f(begin(s)), l(end(s));
if (qi::phrase_parse(f, l, p, qi::space))
std::cout << "Success: " << ctx.xy << "\n";
}

注意:

  • phx::ref() 包装对数据上下文的引用
  • qi::_1 而不是 boost::_1 作为占位符
  • 鉴于 newValueForXY 的实现,您可以轻松编写

        start = qi::double_
    [ phx::bind(&DataContext::xy, phx::ref(dataContext)) = qi::_1 ];

2。使用属性语法,而不是语义操作

但是,我可能会使用属性而不是语义操作来编写相同的示例(因为这基本上就是它们的用途):

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi = boost::spirit::qi;
namespace phx= boost::phoenix;

struct DataContext {
double xy;
};

BOOST_FUSION_ADAPT_STRUCT(DataContext, (double, xy))

template <typename Iterator, typename Skipper>
struct my_grammar : qi::grammar<Iterator, DataContext(), Skipper>
{
my_grammar() : my_grammar::base_type(start) {
start = qi::double_;
}
private:
qi::rule<Iterator, DataContext(), Skipper> start;
};

int main()
{
const std::string s = "3.14";
static const my_grammar<decltype(begin(s)), qi::space_type> p;

DataContext ctx;
if (qi::phrase_parse(begin(s), end(s), p, qi::space, ctx))
std::cout << "Success: " << ctx.xy << "\n";
}

3。使用继承属性传入上下文引用

如果你绝对坚持,你甚至可以使用继承属性来达到目的:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi = boost::spirit::qi;
namespace phx= boost::phoenix;

struct DataContext {
double xy;
};

template <typename Iterator, typename Skipper>
struct my_grammar : qi::grammar<Iterator, void(DataContext&), Skipper> {
my_grammar() : my_grammar::base_type(start)
{
start = qi::double_ [ phx::bind(&DataContext::xy, qi::_r1) = qi::_1 ];
}
qi::rule<Iterator, void(DataContext&), Skipper> start;
};

int main() {
const std::string s = "3.14";
const static my_grammar<std::string::const_iterator, qi::space_type> p;
DataContext ctx;
if(qi::phrase_parse(begin(s), end(s), p(phx::ref(ctx)), qi::space)) {
std::cout << "Success: " << ctx.xy << "\n";
}
}

这在调用站点上更具表现力:

qi::phrase_parse(begin(s), end(s), p(phx::ref(ctx)), qi::space));

并且不要求上下文是默认可构造的。

关于c++ - 是否可以将一个 Action 附加到 boost::spirit::rule 解析器,该解析器将解析结果分配给(尚未)未知实例的成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16675368/

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