我想在一个非常通用的层面上问这个问题:boost::spirit/boost::fusion对容器类型的支持达到了什么程度?有人能给我一些关于什么是可能的和什么是不可能的一般指导吗?
有了"支持",我的意思是:有了以下解析器定义,我可以直接解析为std::pair<double,double>
:
template <typename Iterator>
struct pair_parser
: qi::grammar<Iterator, std::pair<double,double>()>
{
pair_parser() : pair_parser::base_type(start)
{
start = pair;
pair = qi::double_ >> ":" >> qi::double >> ";"
}
qi::rule<Iterator, std::pair<double,double>()> pair;
};
我是否正确理解整个"魔术"是由boost::fusion
完成的?考虑到这一点,让我定义一下:支持一对双打。
我发现了以下方面的工作示例:
std::vector<std::string>
std::map<std::string, std::string> // the trick is not to forget the pair within
std::vector<std::vector<int> >
struct A{int, double, std::string} // with boost::fusion adaptor
我已经计算出以下内容:
std::map<std::string, boost::variant<int, double, std::string> >
因此,我进一步说:
- 字符串向量
- 简单名称值映射
- POD类型的矢量
- 增强::变体
- structs
由boost::spirit
/boost::fusion
支持。
但是,它是否也适用于其他STL容器?它们通常都得到支持吗?还是有些不起作用?提升::容器怎么样?嵌套容器怎么样?它们能嵌套多深?嵌套结构如何?我需要了解什么才能确定容器是否可以与boost::spirit
/boost::fusion
一起使用?
背景:我试图用boost::multi_array
和"double和struct的映射向量"解析成稍微复杂一点的类型,比如struct table
:
struct skewFactor{
double horizontalSkew;
double verticalSkew;
double factor;
};
struct table {
std::vector<std::vector<double> > index;
boost::multi_array<double,4> baseArray; // yes, this array is 4-dimensional
std::vector<std::map<double, skewFactor> > effect;
};
目前,我只是在反复尝试。
boost::spirit
可以很好地处理任意嵌套,只受编译器和硬件限制。
您可能需要(非侵入性地)调整您的类和结构,以便boost::spirit
可以直接解析到它们中。请参阅Employee-解析为结构示例。
显然,我是唯一有兴趣将boost::multi_array
与boost::spirit
一起使用的人。早在2010年,Stephen Torri就对同样的问题感兴趣。
我在上面的struct table;
方面取得了进展。boost::fusion
很好地支持了嵌套的向量、映射和结构。然而,boost::multi_array
仍在等待解决方案。最大的障碍之一是臭名昭著的缺乏好榜样。(我稍后可能会添加一些示例)
嵌套向量和映射的解决方案是由boost::spirit
文档中"深度解析器"部分的研究引发的。我想在上面的一条评论中再次强调我之前的声明:无视boost::spirit documentation
:中的建议"本节不适合胆小的人。"。另一个重要的点是理解boost库本身之间的关系:
- 融合:用于序列化任何数据类型的库。它用于精神语法中的"自动"数据传播
- phoenix:用于函数式编程的库
- 精神:解析器库本身。它建在凤凰城之上。函数式编程是理解解析器和语义动作的关键
对于boost::multi_array
,我决定走另一条路:语义动作。尽管它们在boost::spirit
社区中不受欢迎,但我决定使用它们,因为我还必须在数组中执行一些转换。有了boost::phoenix
,我(几乎)能够在不依赖boost::fusion
的情况下填充阵列。