3

「キャッシュされた計算」/「キャッシュされたゲッター」に共通のパターンまたはすぐに使用できるブーストクラスはありますか?

私はこのようなことを意味します:

class Test{
public:
     Value getValue() const;
protected:
     Value calculateValue() const;//REALLY expensive operation.
     mutable bool valueIsDirty;
     mutable Value cachedValue;
}

Value Test::getValue() const{
     if (valueIsDirty){
         cachedValue = calculateValue();
         valueIsDirty = false;
     }
     return cachedValue;
}

マクロを使用std::pair<Value, bool>して変換することはできますが、値が他の値 (他のクラスに格納されている) に依存し、それらの値もキャッシュできるgetValue/calculateValue場合、これはあまり役に立ちません。

この種の「パターン」にすぐに使用できるソリューションはありますか? 現時点では、このようなキャッシュされた値を手動で処理していますが、これは「きれい」ではありません。

制限:
c++03 標準。ブーストは許可されています。

4

2 に答える 2

1

これは私が最終的に使用したものです:

template<typename T, typename Owner> class CachedMemberValue{
public:
    typedef T (Owner::*Callback)() const;
    T get(){
        if (dirty){
            cachedValue = (owner->*calculateCallback)();
            dirty = false;
        }
        return cachedValue;
    }
    const T& getRef(){
        if (dirty){
            cachedValue = (owner->*calculateCallback)();
            dirty = false;
        }
        return cachedValue;
    }
    void markDirty(){
        dirty = true;
    }
    CachedMemberValue(Owner* owner_, Callback calculateCallback_)
        :owner(owner_), calculateCallback(calculateCallback_), dirty(true){
    }
protected:
    Owner *owner;
    Callback calculateCallback;
    bool dirty;
    T cachedValue;
private:
    CachedMemberValue(const CachedMemberValue<T, Owner>&){
    }
    CachedMemberValue<T, Owner>& operator=(const CachedMemberValue<T, Owner>&){
        return *this;
    }
};

利用方法:

class MyClass{
    public:
        int getMin() const{
            return cachedMin.get();
                }
            void modifyValue() { /*... calculation/modification*/ cachedMin.markDirty();}
        MyClass(): cachedMin(this, &MyClass::noncachedGetMin){}
    private:
        int noncachedGetMin() const{ /*expensive operation here*/ ... }
        mutable CachedMemberValue<int, MyClass> cachedMin;
};
于 2013-07-31T18:23:48.063 に答える
1

Proxy デザイン パターンはこれに役立ちます。

典型的な実装ではValuePtr、通常の と同じように動作するクラスを定義します。Value*つまり、オーバーロードされた and がoperator->ありoperator*ます。ただし、これらの演算子には、基になるオブジェクトに直接アクセスする代わりにValue、実際の値の読み込みまたは再計算を決定するロジックも含まれています。この追加レベルの間接化により、プロキシ ロジックがカプセル化されます。

他のオブジェクトへの参照をカウントする必要がある場合は、 をstd::shared_ptr<Value>内部の基になるデータ型として使用すると便利ですValuePtr

コード例については、このサイトを参照してください。Boost.Flyweightも役立つかもしれません。

于 2013-07-18T11:55:02.660 に答える