首页 文章

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

提问于
浏览
3

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

对数据结构的一次尝试是boost :: fusion :: map(如对this问题的回答中所建议的) . 但是虽然我可以使用boost :: spirit :: qi :: parse()并轻松获取数据,但当我尝试使用karma从它生成文本时,我失败了 .

以下是我的尝试(特别是“map_data”类型) . 经过一些阅读和其他融合类型的讨论,我发现了boost :: fusion :: vector和BOOST_FUSION_DEFINE_ASSOC_STRUCT . 我成功地用它们两者生成输出,但它们似乎并不理想:在向量中你不能使用名称访问成员(它就像一个元组) - 而在另一个解决方案中,我认为我不需要用于访问成员的两种方式(成员名称和密钥类型) .

#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;
}

包括注释行会给出很多编译错误的页面,其中包括:从'boost :: fusion :: pair'到'double'的参数1没有已知的转换没有来自'boost :: fusion的参数1的已知转换::对'浮''

可能是to_string需要map_data的值,而不是对吗?虽然我对模板不熟悉,但我试图通过以下方式使用变换从 Map 中获取矢量

template <typename P>
struct take_second
{
  typename P::second_type operator() (P p)
  {
    return p.second;
  }
};
// ... inside main()
pair <char, int> ff(32);
std::cout << "take_second (expect 32): "
  << take_second<pair<char,int>>()(ff) << std::endl;
std::cout << "transform map_data and to_string: "
  << to_string(boost::fusion::transform(d1, take_second<>())); //*FAIL No 2*

但我不知道在实例化take_second时我应该给出什么类型,无论如何我认为必须有一种更简单的方法来获取(迭代) Map 的值(是吗?)

如果您回答这个问题,请同时就使用ASSOC_STRUCT或 Map 是否更好发表意见 .

1 回答

  • 3

    我想我之前已经注意到了你的问题on the [spirit-general] list .

    它有14个意见 - 我做了一些相当深入的调查 . 可悲的是,据我所知,我不认为Spirit对联合融合结构有任何支持 .

    事实上,在MSM和Phoenix之外,在我看到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;
    }
    

    输出:

    Answer = 42.0
    e = 2.718
    pi = 3.142
    

相关问题