はじめに
- C#に実装されてるようなプロパティ機能をC++11でコンパクト&スマートに実現する方法はないか?
- 将来的にJsonへのシリアライズ/デシリアライズ・GUIとの連携なども実現したい。
と言うのが今回の目的です。
※コードはそのままでは動作してないので適宜修正お願いします。
実装(擬似コード)
参照元 http://codezine.jp/article/detail/7571
property.h
#include <functional>
// クラスのプロパティ一括シリアライズ/デシリアライズのためのインターフェースクラス
class IProperty
{
public:
// シリアライズ関連の純粋仮想関数とか定義
// serializer& serialize(serializer& ar) const = 0;
// serializer& deserialize(serializer& ar) = 0;
};
template<class T>
class Property : public IProperty{
public:
Property() = default;
Property(const property& other) { }
Property& operator=(const Property& other) { set(other.get()); return *this; }
// setter/getter
void operator()(const std::function<T()>& getter, const std::function<T(const T&)>& setter) {
if ( !get ) get = getter;
if ( !set ) set = setter;
}
T operator()() const { return get(); }
T operator()(T const& value) { return set(value); }
operator T() const { return get(); }
T operator=(T const& value) { return set(value); }
// ここにシリアライズ関連関数実装したり
// serializer& serialize(serializer& ar) const {
// ar << get();
//}
// serializer& deserialize(serializer& ar){
// T param;
// ar >> param;
// Set(param);
//}
typedef T value_type;
private:
std::function<T()> get;
std::function<T(const T&)> set;
};
// クラスのプロパティ管理
#define PROP_ARRAY() \
private:std::vector<IProperty*> m_propArray; \
public: \
void SaveProperty(serializer& ar){ \
// m_propArrayの中身を一括シリアライズする処理とか \
} \
void LoadProperty(serializer& ar){ \
// m_propArrayの中身を一括デシリアライズする処理とか \
}
// プロパティ定義(ヘッダ)
#define PROP_DESC(type,param) \
private:type param##_; \
void setup ## param ## (){\
param([this](){return m_##param; },[this](const type& value) { return m_##param = value; });\
}\
public: Property<type> param;
// getter/setter登録(コンストラクタ)
#define PROP_ACTUAL(param) setup ## param ## ()
main.cpp
#include <iostream>
#include <string>
#include "property.h"
using namespace std;
class Person {
public:
Person() {
// get/set のセットアップ
PROP_ACTUAL(Age);
PROP_ACTUAL(Name);
}
// property
PROP_ARRAY();
PROP_DESC(int,Age);
PROP_DESC(std::string,Name);
std::ostream& print_on(std::ostream& out) const { return out << Name_ << ':' << Age_; }
};
ostream& operator<<(ostream& stream, const Person& p) {
return p.print_on(stream);
}
int main() {
Person adam;
adam.Name = "Adam";
adam.Age = 20;
cout << adam << endl;
string name = adam.Name;
int age = adam.Age;
cout << name << ':' << age << endl << endl;
}
これに、libjsonやjsoncpp・picojsonなどのパーサーを組み合わせれば、シリアライズ/デシリアライズもサクッと実装できるかと思います。
これから試したいこと
- Json以外のフォーマット(yaml/MessagePack)も読み書きできるように。
- wxWidgetsやインゲームGUI(AntTweakBar・imguiなど)との連携