LoginSignup
5
2

More than 5 years have passed since last update.

Cereal で optional なフィールドを読み込む

Last updated at Posted at 2016-12-27

漢なら Cereal ですね!

C++のcerealのシリアライズが快適すぎるやばい

Cereal で JSON 形式で設定ファイルのロードに使いたくなりますね!
その場合, 設定パラメータを optional に読む機能がほしくなりますね.

cereal::make_optional みたいなのが提案されているようですが, まだ master には取り込まれていないですね...

そんなわけで, issue の最後のほうにある, exception で囲むやりかたで optional なフィールドを読み込んでみましょう.

こんな感じになりました.
(フィールドは全て NVP(name-value-pair) で読むと仮定)

template <class Archive, class T>
static void Optional(Archive &archive, const std::string &name, T &value) {
  try {
    archive(cereal::make_nvp(name, value));
  } catch (std::exception &e) {
    (void)e;
    // OK
  }
}

// Seralize RenderConfig class.
template <class Archive>
static void LoadRenderConfig(Archive &archive, RenderConfig &m) {
  // Optional fields
  Optional(archive, "width", m.width);
  Optional(archive, "height", m.height);

  // Mandatory fields.
  archive(cereal::make_nvp("eye", m.eye));
  archive(cereal::make_nvp("look_at", m.look_at));
  archive(cereal::make_nvp("up", m.up));
  archive(cereal::make_nvp("fov", m.fov));
}

問題点

構造が深くなって再帰的にロードする場合, Cereal がより上位のレベルで例外を投げてしまい正しくパースができないことがわかりました.
(たとえば, std::vector<MyClass> で, MyClassstd::vector がある場合, MyClass のパースで例外をキャッチしても, std::vector<MyClass> のパースで例外が出てしまう)

また, 同様に構造が深い場合だと, 例外を使ってパースをスキップすると Cereal 側でメモリリークするケースがあります.

以下のようなサンプルも提案されていますが, 定義順が固定になります.

したがって, 今の所完全に optional なフィールドを Cereal で読む手段を実現するのは難しいですね... 設定ファイルをロードするなどの用途では, 普通に JSON パーサや XML パーサを使うしかなさそうです.

まとめ

Cereal すばらしい.

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2