Edited at

C++でプロパティ

More than 3 years have passed since last update.


はじめに


  • 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(AntTweakBarimguiなど)との連携


参考リンク