3

ブーストスピリットを使用してテキストファイルをデータ構造に解析していますが、このデータ構造からテキストを生成し始めています (スピリットカルマを使用)。

データ構造の 1 つの試みは、boost::fusion::map です ( この質問への回答で提案されているように)。しかし、boost::spirit::qi::parse() を使用して簡単にデータを取得できますが、カルマを使用してテキストを生成しようとすると失敗しました。

以下は私の試みです(特に「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 の既知の変換がありません::pair' to 'float'</p>

to_string には、ペアではなく、map_data の値が必要なのではないでしょうか? 私はテンプレートが苦手ですが、次の方法で変換を使用してマップからベクトルを取得しようとしました

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 をインスタンス化するときにどの型を指定すればよいかわかりません。とにかく、マップの値を取得 (反復) する簡単な方法が必要だと思います (ありますか?)

この質問に答える場合は、ASSOC_STRUCT とマップのどちらを使用するのが良いかについても意見をお聞かせください。

4

1 に答える 1

3

[spirit-general]リストであなたの質問に気付いたと思います。

そこには 14 のビューがあり、かなり詳細な調査を行いました。悲しいことに、私の知る限りでは、Spirit は関連する Fusion 構造をサポートしていないと思います。

実際、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;
}

出力:

Answer = 42.0
e = 2.718
pi = 3.142
于 2012-11-15T01:08:49.687 に答える