LoginSignup
15
20

More than 5 years have passed since last update.

C++でプロパティ

Last updated at Posted at 2015-10-28

はじめに

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

参考リンク

15
20
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
15
20