ゆとりーなの日記

日記的な事を書いて行くと思はれる

Boostのfusionとspiritやばい

CSVの中身を構造体に読み込むならもうこのコンビ一択でいいですね。
data.csv

ハリード,21,12,20,17,15,19,20
カイ,10,18,20,13,24,16,21
コーデリア,20,12,18,20,11,19,20
ゲラ=ハ,18,21,16,22,16,18,15
キャット,16,22,25,10,15,14,21
レッド,20,14,18,17,11,23,17

ソース

#include <fstream>
#include <iostream>
#include <vector>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/algorithm/transform.hpp>
#include <boost/spirit/include/phoenix.hpp>
#pragma warning(disable: 4819) // VCだと文字コードがどうとかうるさいので警告を消す
#include <boost/spirit/include/qi.hpp>
#pragma warning(default: 4819)
#include <pstade/oven/copied.hpp>
#include <pstade/oven/stream_lines.hpp>
#include <pstade/oven/transformed.hpp>

struct data {
  std::string namae;
  int wanryoku;
  int kiyosa;
  int subayasa;
  int tairyoku;
  int maryoku;
  int seishin;
  int miryoku;
};

BOOST_FUSION_ADAPT_STRUCT(
  data,
  (std::string, namae)
  (int, wanryoku)
  (int, kiyosa)
  (int, subayasa)
  (int, tairyoku)
  (int, maryoku)
  (int, seishin)
  (int, miryoku)
)

struct parse {
  template <typename T>
  struct result {
    typedef data type;
  };

  data operator ()(const std::string &x) const {
    data d;
    boost::spirit::qi::parse(x.begin(), x.end(), *(boost::spirit::qi::char_ - ",") >> "," >> 
                                                 boost::spirit::qi::int_ >> "," >> 
                                                 boost::spirit::qi::int_ >> "," >>
                                                 boost::spirit::qi::int_ >> "," >>
                                                 boost::spirit::qi::int_ >> "," >>
                                                 boost::spirit::qi::int_ >> "," >>
                                                 boost::spirit::qi::int_ >> "," >>
                                                 boost::spirit::qi::int_, d);
    return d;
  }
};

int main() {
  std::ifstream fin("data.csv");
  const std::vector<data> v = pstade::oven::stream_lines(fin) | pstade::oven::transformed(parse()) | pstade::oven::copied;
  boost::for_each(v, [](const data &x) {
    std::cout << "名前:" << x.namae <<
                 ",腕力:" << x.wanryoku << 
                 ",器用さ:" << x.kiyosa << 
                 ",すばやさ:" << x.subayasa << 
                 ",体力:" << x.tairyoku << 
                 ",魔力:" << x.maryoku << 
                 ",精神:" << x.seishin << 
                 ",魅力:" << x.miryoku << std::endl;
  });
  return 0;
}

出力

名前:ハリード,腕力:21,器用さ:12,すばやさ:20,体力:17,魔力:15,精神:19,魅力:20
名前:カイ,腕力:10,器用さ:18,すばやさ:20,体力:13,魔力:24,精神:16,魅力:21
名前:コーデリア,腕力:20,器用さ:12,すばやさ:18,体力:10,魔力:11,精神:19,魅力:20
名前:ゲラ=ハ,腕力:18,器用さ:21,すばやさ:16,体力:22,魔力:16,精神:18,魅力:15
名前:キャット,腕力:16,器用さ:22,すばやさ:25,体力:10,魔力:15,精神:14,魅力:21
名前:レッド,腕力:20,器用さ:14,すばやさ:18,体力:17,魔力:11,精神:23,魅力:17

エラーチェックとか日本語名によっては残念な結果になってしまうかもしれないのでもうちょっと正確に書いたほうがいいのでしょうが、取り敢えずこんな感じでCSVファイルの中身を構造体に読み込めるのはおいしいです。
追記:
yak_ex先生によるauto_を使った読込例です。パースにルールをいちいち渡す必要がなくなっていてすむので一度書いてしまえばどんな構造体にも対応できるみたいです。
Boost.Spirit.Qi の auto_ パーサーでカンマ区切りのデータを Fusion シーケンスに突っ込む | Yak!の日記 | スラド