boost::spirit::qi具有相同的简单自适应结构属性的规则会导致编译错误
boost::spirit::qi Rules with identical simple adapted struct attributes give compile error
我想重用一个规则,只需在它前面加一个关键字。所以我的规则是这样的:
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <string>
namespace qi = boost::spirit::qi;
struct A {
int index;
std::string name;
};
BOOST_FUSION_ADAPT_STRUCT(::A, (int, index)(std::string, name))
struct B {
A data;
};
BOOST_FUSION_ADAPT_STRUCT(::B, (A, data))
int main() {
typedef std::string::const_iterator iterator_type;
qi::rule<iterator_type, A()> a_rule = qi::int_ > qi::lit(",") > *(qi::char_);
qi::rule<iterator_type, B()> b_rule = qi::lit("(") > a_rule > qi::lit(")");
qi::rule<iterator_type, B()> bad_rule = qi::lit("keyword") > b_rule;
return 0;
}
这不会编译,因为编译器想要从B
创建A
(指bad_rule的定义):
C:/tc/gcc_x64_4.8.1_win32_seh_rev1/mingw64/my/src/boost_1_54_0/boost/spirit/home/qi/detail/assign_to.hpp:152:18: error: no matching function for call to 'A::A(const B&)'
attr = static_cast<Attribute>(val);
^
然而,将struct B
更改为不那么简单,可以使其工作:
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <string>
namespace qi = boost::spirit::qi;
struct A {
int index;
std::string name;
};
BOOST_FUSION_ADAPT_STRUCT(::A, (int, index)(std::string, name))
struct B {
A data;
int dummy;
};
BOOST_FUSION_ADAPT_STRUCT(::B, (A, data)(int, dummy))
int main() {
typedef std::string::const_iterator iterator_type;
qi::rule<iterator_type, A()> a_rule = qi::int_ > qi::lit(",") > *(qi::char_);
qi::rule<iterator_type, B()> b_rule = qi::lit("(") > a_rule > qi::lit(")") > qi::attr(0);
qi::rule<iterator_type, B()> bad_rule = qi::lit("keyword") > b_rule;
return 0;
}
有什么想法吗?没有这个变通办法怎么相处?这里发生了什么?
这又是调整单个元素序列的问题。不幸的是,我不知道这种情况的解决方法。在这种情况下,您可以删除B的自适应并专门化transform_attribute
。这里有一个简单的例子,它几乎完全符合您的要求。
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <string>
namespace qi = boost::spirit::qi;
struct A {
int index;
std::string name;
};
BOOST_FUSION_ADAPT_STRUCT(::A, (int, index)(std::string, name))
struct B {
A data;
};
namespace boost{ namespace spirit{ namespace traits
{
template <>
struct transform_attribute<B,A,qi::domain>
{
typedef A& type;
static type pre(B& val){ return val.data;}
static void post(B&, A const&){}
static void fail(B&){}
};
}}}
int main() {
typedef std::string::const_iterator iterator_type;
qi::rule<iterator_type, A()> a_rule = qi::int_ >> qi::lit(",") >> *(qi::char_-qi::lit(")"));
qi::rule<iterator_type, B()> b_rule = qi::lit("(") >> a_rule >> qi::lit(")");
qi::rule<iterator_type, B()> bad_rule = qi::lit("keyword") >> b_rule;
std::string test="keyword(1,one)";
iterator_type iter=test.begin(), end=test.end();
B b;
bool result = qi::parse(iter,end,bad_rule,b);
if(result && iter==end)
{
std::cout << "Success:" << std::endl;
std::cout << "b.data.index=" << b.data.index << ", b.data.name=" << b.data.name << std::endl;
}
else
{
std::cout << "Failed. Unparsed: " << std::string(iter,end) << std::endl;
}
return 0;
}
一个更简单的解决方法是放弃自动属性传播,而是将显式赋值写成一个琐碎的语义操作:
qi::rule<iterator_type, B()> bad_rule = "keyword" > b_rule[ qi::_val=qi::_1 ];
我同意这仍然是一个痛苦的解决办法。Spirit V3承诺简化这里的机制,并使属性兼容性在边缘更加平滑。
相关文章:
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 此代码是否违反一个定义规则
- C++概念:如何使用'concept'检查模板化结构的属性?
- 生成文件不对文件使用隐式规则
- 子目录是否继承属性,例如add_definitions,include_directories和父Cmakelist.t
- 通过指向指针数组的指针访问子类的属性
- MSVC是否支持C++11样式的属性而不是__declspec
- 精神X3,如何获得属性类型以匹配规则类型
- 精神 X3:本地定义的规则定义必须附加属性
- qi ::以继承属性为继承属性的规则
- 为什么 boost::qi 规则的属性必须用括号声明?
- 将属性传递给提升精神的子规则
- 在提升精神因果报应中,如何可能将属性传递给子规则
- 如何使用 boost::tuple 作为 boost::spirit 规则中的属性
- boost::spirit::qi具有相同的简单自适应结构属性的规则会导致编译错误
- 重复的属性传播规则 (%)
- 从语义操作返回的值会干扰规则属性
- 振奋精神,为什么需要as<>指令?(又名帮助我了解属性兼容性规则)
- 精神解析器属性传播规则的问题
- 规则属性的兼容性