C++ 在boost::spirit::karma中使用boost::fusion::map

C++ 在boost::spirit::karma中使用boost::fusion::map,c++,boost-spirit,boost-fusion,C++,Boost Spirit,Boost Fusion,我正在使用boost spirit将一些文本文件解析为数据结构,现在我开始从这个数据结构生成文本(使用spirit karma) 数据结构的一种尝试是boost::fusion::map(如对 问题)。但尽管我可以使用boost::spirit::qi::parse()并轻松获取其中的数据,但当我尝试使用karma从中生成文本时,我失败了 下面是我的尝试(请特别关注“map_data”类型)。在阅读了一些其他融合类型的内容并对其进行了研究之后,我找到了boost::fusion::vector和

我正在使用boost spirit将一些文本文件解析为数据结构,现在我开始从这个数据结构生成文本(使用spirit karma)

数据结构的一种尝试是boost::fusion::map(如对 问题)。但尽管我可以使用boost::spirit::qi::parse()并轻松获取其中的数据,但当我尝试使用karma从中生成文本时,我失败了

下面是我的尝试(请特别关注“map_data”类型)。在阅读了一些其他融合类型的内容并对其进行了研究之后,我找到了boost::fusion::vector和boost\u fusion\u DEFINE\u ASSOC\u STRUCT。我成功地使用这两种方法生成了输出,但它们似乎并不理想:在vector中,您无法使用名称(类似于元组)访问成员——在另一种解决方案中,我认为访问成员不需要两种方法(成员名称和键类型)

#include <iostream>
#include <string>
#include <boost/spirit/include/karma.hpp>
#include <boost/fusion/include/map.hpp>
#include <boost/fusion/include/make_map.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/transform.hpp>

struct sb_key;
struct id_key;

using boost::fusion::pair;

typedef boost::fusion::map
  < pair<sb_key, int>
  , pair<id_key, unsigned long>
  > map_data;

typedef boost::fusion::vector < int, unsigned long > vector_data;

#include <boost/fusion/include/define_assoc_struct.hpp>
BOOST_FUSION_DEFINE_ASSOC_STRUCT(
    (), assocstruct_data,
    (int, a, sb_key)
    (unsigned long, b, id_key))

namespace karma =  boost::spirit::karma;

template <typename X>
std::string to_string ( const X& data )
{
  std::string generated;
  std::back_insert_iterator<std::string> sink(generated);
  karma::generate_delimited ( sink, karma::int_ << karma::ulong_, karma::space, data );
  return generated;
}

int main()
{
  map_data d1(boost::fusion::make_map<sb_key, id_key>(234, 35314988526ul));
  vector_data d2(boost::fusion::make_vector(234, 35314988526ul));
  assocstruct_data d3(234,35314988526ul);

  std::cout << "map_data as_vector: " << boost::fusion::as_vector(d1) << std::endl;
  //std::cout << "map_data to_string: " << to_string(d1) << std::endl; //*FAIL No 1*
  std::cout << "at_key (sb_key): " << boost::fusion::at_key<sb_key>(d1) << boost::fusion::at_c<0>(d1) << std::endl << std::endl;

  std::cout << "vector_data: " << d2 << std::endl;
  std::cout << "vector_data to_string: " << to_string(d2) << std::endl << std::endl;

  std::cout << "assoc_struct as_vector: " << boost::fusion::as_vector(d3) << std::endl;
  std::cout << "assoc_struct to_string: " << to_string(d3) << std::endl;
  std::cout << "at_key (sb_key): " << boost::fusion::at_key<sb_key>(d3) << d3.a << boost::fusion::at_c<0>(d3) << std::endl;

  return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
构造sb_键;
结构id_键;
使用boost::fusion::pair;
typedef boost::fusion::map
<对
一对
>地图数据;
typedef boost::fusion::vectorvector\u数据;
#包括
增强\融合\定义\关联\结构(
(),assocstruct_数据,
(int、a、sb_键)
(无符号长,b,id_键))
名称空间业力=提升::精神::业力;
模板
std::字符串到_字符串(常量X和数据)
{
std::生成的字符串;
std::back\u insert\u迭代器接收器(已生成);

karma::generate_delimited(sink,karma::int_p>我想我之前注意到了你的问题

它有14个视图-我做了一些相当深入的调查。不幸的是,据我所知,我认为Spirit对关联融合结构没有任何支持

事实上,除了MSM和Phoenix,在boost中我没有看到使用fusion::map的地方

有没有可能只使用std::map/std::pair来代替呢?这里有一个小小的概念证明:

#include <boost/spirit/include/karma.hpp>
#include <boost/fusion/adapted.hpp>

int main()
{
    const auto data = std::map<std::string, double> { 
        { "pi", 3.1415925 }, 
        { "e", 2.718281828 }, 
        { "Answer", 42 } };

    namespace karma = boost::spirit::karma;
    std::cout << karma::format((karma::string << " = " << karma::double_) % karma::eol, data)
              << std::endl;
}

谢谢你的回答。事实上,我的数据结构有两个以上的字段,所以我不能使用std::pair。我想我可以使用fusion::map,因为它是一个正向序列。我猜它将类似于std::tuple或adapted struct或fusion associative struct。好的,std::tuple或boost::tuple可以工作。无论如何,如果y你真的必须使用融合关联结构,在这个答案中找到一个补丁来添加“
at_key
”支持:-你仍然会被限制在语义操作上,但如果你想要对融合贴图作为属性提供全面的一流支持,你可能应该使用自定义点:参见例如,和Spirit文档:
#include <boost/spirit/include/karma.hpp>
#include <boost/fusion/adapted.hpp>

int main()
{
    const auto data = std::map<std::string, double> { 
        { "pi", 3.1415925 }, 
        { "e", 2.718281828 }, 
        { "Answer", 42 } };

    namespace karma = boost::spirit::karma;
    std::cout << karma::format((karma::string << " = " << karma::double_) % karma::eol, data)
              << std::endl;
}
Answer = 42.0
e = 2.718
pi = 3.142