ゆとりーなの日記

日記的な事を書いて行くと思はれる

boostは簡単なサンプルはあるけど実用的な使用例が少ないねって言われたので簡単なサンプルをあげてみる

DirectXでテクスチャを管理する際キャッシュするとすれば、まあ画像ファイル名をキーにしてマップ管理するのが普通だと思うのですが、この管理ルーチンを書くのは地味に面倒です。そこでこれらを自動でやってくれるboost.flyweightの出番と言うわけです。
boost.flyweightFlyweightパターンというデザインパターンの実装らしいので、詳しくはFlyweightパターンでGoogle先生なりに聞いてみると幸せになれると思います。
まずは、中身に入れるクラスというか構造体を作ります。

struct TextureHandle {
    explicit TextureHandle(const std::string &texture_name) : texture(nullptr) {
      // textureにD3DXCreateTextureFromFileで作ったIDirect3DTexture9*を入れる。
    ~TextureHandle() {
        if (texture) {
            texture->Release();
        }
    }
    IDirect3DTexture9 *texture;
};

IDirect3DTexture9*を使う場面では、次のように書きます。

#include <boost/flyweight.hpp>
#include <boost/flyweight/key_value.hpp>

class Object {
public:
    Object(float x, float y) : texture_("オブジェクト.png"), draw_pos_x_(x), draw_pos_y(y) {
    }
    void draw() {
        // IDirect3DTexture9*を取りだす
        IDirect3DTexture9 *texture(texture_.get().texture);
        // 描画コード等々
    }
private:
    boost::flyweights::flyweight<boost::flyweights::key_value<std::string, TextureHandle>> texture_;
    float draw_pos_x_;
    float draw_pos_y_;
};

これで完成です。Objectをいくつ生成しても、既にObjectのインスタンスが存在していれば、TextureHandleを共有してくれます。これ経由で描画してやればいいわけです。しかも、幸せなことに、Objectのインスタンスが全滅すると、TextureHandleも消滅するという有情仕様。場合によってはこの仕様は迷惑と思うかもしれませんが、no_tracking等のオプションを使えば、その辺は変えられるみたいです。
ミソはboost::flyweights::key_valueの部分ですね。通常自作の型をboost.flyweightに入れる場合ハッシュ関数等自作しなければいけないものが多いのですが、boost::flyweights::key_valueを使うことで、std::string等、既存のハッシュ関数がある型をキーとして使うことが出来ます。