Boost.Propertyの使い方

typoに突っ込んだだけだと嫌なのでwちょっと解説を書いてみる.
ネタ元:Boost.Property実装案? -> id:xyuyuxさんが簡略化 -> C++でPropertyつづき1
簡略化された方についてです.(本家は長いのでパス)

使用例

class Hoge {
	template< typename Base >
	struct prop : public Base
	{
		std::string get() const { return arg_; }
		void set(std::string const & str) {
			arg_ = str;
			// cygwin g++ 3.4.4で怒られるorz
			// this->self()->msglength = str.length();
			*static_cast<int*>(&this->self()->msglength) = str.length();
			this->self()->setter_hook(); // フックしてるところ
		}
	private:
		std::string arg_;
	};
	void setter_hook() const
	{ std::cout << "call setter>" << msg.get() << std::endl; }
public:
	MY_PROPERTY( prop, Hoge, msg );
	string msglength;
};

使い方

  1. テンプレート引数を継承するinnerテンプレートクラス(prop)を書く
  2. 持たせたい属性?とメンバとset()/get()を書く
  3. マクロMY_PROPERTY()で属性の名前を宣言する
    • ややこしいクラスに展開される
  4. Baseから継承したself()を呼び出すとなぜかouterクラスのポインタが得られる*1ので使ってみたりする
  5. 使ってみる
int main() {
  using namespace std;
  Hoge h;
  h.msg = string("www.example.org");
  cout << "> h.msg " << h.msg.get() << " h.strlength " << h.strlength << endl;

  string header("/index.html");
  h.msg = h.msg.get() + header;
  // 勝手に変化してる
  cout << "> h.msg " << h.msg.get() << " h.strlength " << h.strlength << endl;
  return 0;
}

注意

出来上がった属性はgetter/setterで扱う型とは違うので,そのまま使うことは出来ない.
上のコードだと,

 void setter_hook() const
 { std::cout << "call setter>" << msg << std::endl; }

とはできないので注意.勝手に持たされてるはずのmsg.get()を呼び出すこと.

まとめ

パッと見いまいち利点が分からないなーと思ったけど,属性が複数ある場合に,
ある属性を変更すると連動して勝手に変更される属性が定義できるところがアレゲでよろしい.

本家だとr/thetaをこれで同期してる.よくx/y座標と極座標のどっちでメンバ持たせようか悩むので便利かもしれない.

*1:むしろここが肝なのか?!