2017年6月7日 Theolizer®最新版v1.1.0へ対応するために修正しました。
最新版のソース一式をGistに置いてます。

こんにちは。田原です。

プログラムの開発中に構造体やクラス、enum型の定義変更は日常茶飯事ですね。そして、古いプログラムで保存したファイルを新しいプログラムで読む必要があります。Theolizer®ではこれらに2種類の方法を組み合わせて対処します。今回は定義の変更方法について解説し、次回はバージョン・アップ/ダウン処理について解説します。

1.どんな変更が可能なのか

1-1.クラスと構造体の場合

クラスや構造体はメンバ変数を1つ1つ自動的に保存しますが、その時メンバ変数とその値の対応方法として2種類用意しています。

  1. メンバ変数名で対応
    変数名で対応しているので定義順序を変更できます。また、任意の場所に追加できますし、任意の変数を削除できます。
    クラスや構造体が若い内に使うモードです。デフォルトではこのモードとなります。今回はこちらについて説明します。

  2. クラス/構造体内の定義順で対応
    順序だけで対応していますので、順序が狂うような変更はできません。メンバ変数リストの最後のみ追加/削除が可能です。
    しかし、ある程度枯れてきたら、変数名をシリアライズ・データへ記録することが勿体無く感じます。そのような時に使う機能です。

1-2.enum型の場合

enum型はその設定値をシンボル名、もしくは、シンボル値のどちらかで保存できます。

  1. シンボル名で保存
    enum型の変数に格納されている値を文字列としてシンボル名にて保存します。つまり、値を変更してもシンボル名を変更していなければ変更前に保存されたデータを適切に回復できます。
    enum型が若い内に使うモードです。デフォルトではこのモードとなります。今回はこちらについて説明します。

  2. シンボル値で保存
    enum型の変数に格納されている値を数値型でそのまま保存します。
    値だけを保存しますので、シリアライズ・データへの負担が小さいです。枯れたenum型で使用する機能です。

2.サンプル・プログラム

今回はシリアライズ・データの内容を良く見た方がよいので、家計簿アプリは使いません。
小さな小さなenum型と構造体を保存/回復するコードを書きました。

2-1.変更前のプログラム

2-1-1.構造体定義
main_a.h
2-1-2.データの保存と回復
main_a.cpp
2-1-3.自動生成されたソース
main_a.cpp.theolizer.hpp

enum型Fooの変数aFooA, aFooBは値ではなくシンボル名(”eFoo1″, “eFoo2″)で保存されています。

2-1-4.保存されたファイル
test.json
2-1-5.実行結果
result_a.log

2-2.変更後のプログラムで変更前のプログラムのデータを読む

enum型Fooはシンボル値を変え、シンボルを増やしました。
構造体Barはメンバ変数の順序を変更、メンバ変数mBar0を削除、メンバ変数mBar3を追加しました。

2-2-1.構造体定義
main_b.h
2-2-2.データの保存と回復
main_b.cpp
2-2-3.自動生成されたソース
main_b.cpp.theolizer.hpp

main_a.exeを実行し、test.jsonを生成した後、main_b.exe Lを実行しました。
main_b.exeにパラメータLを指定することで保存処理をスキップしtest.jsonを回復します。
以上の操作により、変更前のプログラムが保存したtest.jsonを変更後のプログラムが回復した結果となります。
enum型Fooがシンボル名で回復されているため、変更後のプログラムの値が回復されています。
構造体Barは変更前に存在していたメンバ変数(mBar1, mBar2)について適切に回復されています。新規追加されたmBar3は初期値のままを維持しています。そして、削除されたmBar0については破棄しますので問題を引き起こしません。

2-2-4.CMakeLists.txt

CMakeLists.txt
2-2-5.実行結果
result_bL.log

2-3.変更後のプログラムで自分のプログラムのデータを読む

もちろん、変更後のプログラムは自分が保存したデータを読めます。
以下はmain_b.exeをパラメータ無しで起動し、自分が保存したデータを自分で回復した時の結果です。

2-3-1.保存されたファイル
test.json
2-3-2.実行結果
result_b.log

3.まとめ

このようにメンバの追加/変更程度であれば、比較的お手軽に変更できます。
enum型については、更にシンボル名やシンボル値を変更した時の追従機能もありますが、それはまた別の機会に説明したいと思います。